滑动窗口最大值
给你一个整数数组 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]
思路一
var maxSlidingWindow = function (nums, k) {
let result = [];
for (let i = 0; i <= nums.length - k; i++) {
let max = nums[i];
for (let j = 1; j < k; j++) {
if (nums[i + j] > max) {
max = nums[i + j];
}
}
result.push(max);
}
return result;
};
讲解
两个循环解决问题。
外层循环:遍历 从 0 到 nums.length - k,每次确定一个 窗口的起始位置 。
内层循环:在当前窗口内 (从 i 到 i + k - 1) 查找最大值。
然后将值存储到 result 中就行。
思路二
var maxSlidingWindow = function (nums, k) {
let result = [];
let deque = []; // 用于存储索引
for (let i = 0; i < nums.length; i++) {
// 移除不在窗口内的元素
if (deque.length && deque[0] < i - k + 1) {
deque.shift();
}
// 移除小于当前元素的索引
while (deque.length && nums[deque[deque.length - 1]] < nums[i]) {
deque.pop();
}
// 添加当前元素的索引
deque.push(i);
// 当窗口达到大小 k 时,记录当前窗口的最大值
if (i >= k - 1) {
result.push(nums[deque[0]]);
}
}
return result;
};
讲解
具体的解题思路:
- 滑动窗口:我们可以使用一个大小为 k 的窗口,从数组的左侧开始,逐步向右滑动。
- 双端队列:使用一个双端队列(deque)来存储当前窗口内的元素的索引。这个队列的特点是:
队列的头部始终存储当前窗口的最大值的索引。
队列中的索引是单调递减的,即队列头部的元素对应的值是当前窗口内最大的。具体分析
- 初始化:创建一个空的结果数组 result 和一个空的双端队列 deque。
- 遍历数组:对于每个元素 nums[i]:
移除过期元素:检查队列的头部,如果它的索引小于 i - k + 1(表示该索引不在当前窗口内),则将其移除。
保持单调性:在添加新元素之前,移除队列中所有小于当前元素的索引。这是因为这些元素在当前窗口中不可能是最大值。
添加当前元素的索引:将当前元素的索引 i 添加到队列中。
记录最大值:当 i大于等于 k - 1 时,将队列头部的元素(即当前窗口的最大值)添加到结果数组中。关键点
双端队列的使用:它的特性使得我们能够快速地添加和移除元素,同时保持当前窗口的最大值在队列的头部。
窗口的更新:通过维护一个有效的索引集合,我们能够在短时间内获取当前窗口的最大值,避免了重复计算。
:滑动窗口最大值&spm=1001.2101.3001.5002&articleId=141858230&d=1&t=3&u=3c3e1448e1f74949a1ae5351ceca253f)
427

被折叠的 条评论
为什么被折叠?



