题解 | #滑动窗口最小值#
滑动窗口最小值
https://www.nowcoder.com/practice/f461dfe66f804263bac32e13c05178fa?tpId=363&tqId=10616032&ru=/exam/oj&qru=/ta/super-company23Year/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D363
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param nums int整型一维数组
* @param k int整型
* @return int整型一维数组
*/
/**
方法一:双向队列(链表) 时间复杂度O(n) 数学模拟居多 妙!!!
*/
public int[] minSlidingWindow(int[] nums, int k) {
// deque存放的是元素的索引值,而不是元素!!!
Deque<Integer> deque = new LinkedList<>();
int [] result = new int[nums.length - k + 1];
// 结果数组的索引
int index = 0;
for (int i = 0; i < nums.length; i++) {
// 移除已经不在窗口内的元素
if ((!deque.isEmpty()) && (deque.peekFirst() < i - k + 1)) {
// peekFirst是返回队首元素,但不删除,pollFirst是要做删除操作
deque.pollFirst();
}
// 移除窗口内比当前元素还要大的元素,因为肯定不是最小值,从队尾开始移除,保持元素的递增顺序
while ((!deque.isEmpty()) && (nums[deque.peekLast()] > nums[i])) {
deque.pollLast();
}
// 将当前元素索引添加到队尾
deque.offerLast(i);
// 如果窗口长度已经到达k-1,说明可以找最小值了,比如i=2,k=3
if (i >= k - 1) {
if (!deque.isEmpty()) {
// 防止deque.peekFirst出现空指针异常
result[index++] = nums[deque.peekFirst()];
}
}
}
return result;
}
/**
方法二:优先级队列 时间复杂度O(nlogk) k是堆的节点数 也就是窗口大小 比暴力解法还是好不少
*/
public int[] minSlidingWindow(int[] nums, int k) {
// 优先级队列 (小根堆,保存最小值)
PriorityQueue<Integer> queue = new PriorityQueue<>();
// 窗口左边界
int left = 0;
// 窗口右边界
int right = 0;
// 结果数组索引
int index = 0;
// 初始化操作
while (right < k) {
queue.add(nums[right++]);
}
int[] result = new int[nums.length - k + 1];
// 初始化第一个最小值
if (!queue.isEmpty()) {
result[index++] = queue.peek();
}
// 当右边界小于数组长度时
while (right < nums.length) {
// 窗口向右移动 先删除左边界的元素
queue.remove(nums[left]);
// 左边界扩张
left++;
// 添加新的右边界元素
queue.add(nums[right]);
// 右边界扩张
right++;
// 拿取此时小根堆的顶部元素
if (!queue.isEmpty()) {
result[index++] = queue.peek();
}
}
return result;
}
}
本题知识点分析:
1.双向队列(链表)单调
2.优先级队列(小根堆,可以自定义,new Comparator就可以,建议Lambda表达式简写,(o1,o2)->(o2-o1)即可
3.数学模拟
4.队列存取
本题解题思路分析:
1.双向队列是方法一,数学模拟的思想居多,存储索引值,然后保持队列的递增特性,每次取出队首
2.优先级队列数学模拟就比较简单,缩减和扩展,小根堆内部排序,不用自己操作,唯一就是时间复杂度增加了
3.其他细节看注释就可以了,非常详细
本题使用编程语言: Java
建议大家还是多掌握几种做题的解法,暴力能不用就不用,因为面试的时候基本都是有要求的,暴力做出来大多数也是无用功,多用数据结构、常见API、算法类型、剪枝优化。
如果本篇文章对你有帮助的话,可以点个赞,有问题可以评论区留言,感谢支持~

睿联技术公司福利 62人发布