题目描述
给你一个整数数组 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]
思路&js代码
1、单调队列
维护一个双端队列 queue,使得队列中的索引对应的 nums 值是 单调递减 的。 每次滑动窗口时:
- 先移除队列中不在窗口范围内 的元素(i - k) 之前的。
- 再从队列尾部移除比当前 nums[i] 小的元素,保证队列单调递减。
- 队列头部元素始终是窗口内的最大值,存入 ans。
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
//单调队列,保存最大的k个值
/*
1. 维护一个双端队列 queue,使得队列中的索引对应的 nums 值是 单调递减 的。
2. 每次滑动窗口时:
3. 先移除队列中不在窗口范围内 的元素(i - k) 之前的。
4. 再从队列尾部移除比当前 nums[i] 小的元素,保证队列单调递减。
5. 队列头部元素始终是窗口内的最大值,存入 ans[]。
*/
var maxSlidingWindow = function(nums, k) {
let ans = [];
let queue = []; // 存储元素索引,维护单调递减队列
for (let i = 0; i < nums.length; i++) {
// 移除窗口外的元素,意思就是最大值如果不在滑动窗口内部就去掉他,同时每次移动一步,所以只需要判断一次。
if (queue.length > 0 && queue[0] < i - k + 1) {
queue.shift();
}
// 维护单调递减队列,移除比当前值小的元素
while (queue.length > 0 && nums[queue[queue.length - 1]] < nums[i]){
queue.pop();
}
// 加入当前元素索引
queue.push(i);
// 记录窗口最大值(窗口形成后)
if (i >= k - 1) {
ans.push(nums[queue[0]]);
}
}
return ans;
};