题目名称:滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。
示例:
输入: 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
解法
最大值比较
- 先获取第一个窗口的最大值,后面加入的依次比较,主要比较两种情况:
- 1、新加入的值是否大于当前区间内最大值? -> 是则重置最大值
- 2、从队列尾部移出的元素是否为当前区间最大值? -> 是则重新计算最大值
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var maxSlidingWindow = function (nums, k) {
if (!nums.length) return []
const res = []
const stack = []
let max = null
// * 找最大值
function findMax(list) {
let max = -Infinity
for (let i = 0; i < list.length; i++) {
const val = list[i]
max = val > max ? val : max
}
return max
}
for (let i = 0; i < k; i++) {
const val = nums[i]
stack.push(val)
}
max = findMax(stack)
res.push(max)
for (let i = k; i < nums.length; i++) {
const val = nums[i]
const tail = stack.shift()
stack.push(val)
if (val >= max) {
// 如果新加入的值比当前最大值还要大
max = val
} else if (tail === max) {
// 如果新加入的值没有最大值大并且shift出去的值就是当前最大值
max = findMax(stack)
} else {
// 新加入的值没有当前最大值大,并且shift出去的也不是当前最大值,那就不用动
}
res.push(max)
}
return res
}
测试用例
// 测试用例
let nums = [1, 3, -1, -3, 5, 3, 6, 7],
k = 3
console.time("执行用时")
console.log(maxSlidingWindow(nums, k))
console.timeEnd("执行用时")
总结
- 滑动窗口常见解法有维持双端队列,让最大值一直处于头部,这种方法极其巧妙的同时也让人极其费解
- 本解法简化双端队列思想,反而关注新加入的值和弹出的值,比较容易理解
说明
- 本题解已同步GitHub地址,可以复制代码进行调试。
- 总结出了一套亲测有效的前端无痛刷题项目,有助于算法小白平稳入门,详见leetcode-js-roadmap,希望对从零开始刷题的前端小伙伴们带来帮助~
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情