难度:Hard
题目:
给你一个整数数组
nums
,有一个大小为k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k
个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 1 [3 -1 -3] 5 3 6 7 3 1 3 [-1 -3 5] 3 6 7 5 1 3 -1 [-3 5 3] 6 7 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
示例 2:
输入:nums = [1], k = 1 输出:[1]
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
Related Topics
- 队列
- 数组
- 滑动窗口
- 单调队列
- 堆(优先队列)
重点!!!解题思路
第一步:
明确解题思路:像这种滑动窗口的题一半都是维护一个单调队列来解答
第二步:
如果想要每次获得窗口的最大值,就相当于维护这个队列(这个队列相当于窗口),
让这个队列保持一个降序排序,那么队列的头部就是最大值,
当窗口移动时,队列可以尾部出队,头部也可以出队,那么这个队列就是一个双端队列 ,
知道这些即可做题了。
讲解+源码:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
ArrayList<Integer> res=new ArrayList<>(); //初始化结果集
Deque<Integer> queue=new ArrayDeque<>(); //初始化双端队列
for (int i=0;i<nums.length;i++){ //遍历数组
while (!queue.isEmpty() && queue.peekFirst()<i-k+1) queue.pollFirst(); //如果当前队列的头部不在窗口的范围内,就让他poll掉
while (!queue.isEmpty() && nums[queue.peekLast()]<nums[i]) queue.pollLast(); //如果当前遍历的值比尾部的值大,那么就让尾部出队,因为我们要降序的队列
queue.add(i); //每次添加的都是下标值
if (i>=k-1){ //当窗口完全进入数组时才能算最大值
res.add(nums[queue.peekFirst()]);
}
}
return res.stream().mapToInt(Integer::valueOf).toArray(); //集合转换为数组的方式
}
}
GPT解释:
运行结果:
系列持续更新中,喜欢练习算法的那就点个攒吧