「这是我参与2022首次更文挑战的第40天,活动详情查看:2022首次更文挑战」
题目介绍
原题目请见上方链接
解题思路
这道题很容易想到的做法是先取前 k 个数字,然后获取这 k 个数字中的最大值,插入到结果数组中,然后再往后移动一位,再次获取 k 个数字中的最大值,一直到遍历完整个数组,但是这样需要执行 nums.length - k + 1 次比较 k 个数的大小,并且前后两次比较之间其实只有一个数是不同的,这样的效率太低
接下来我们利用队列的思想来看一下下面的这种做法:
- 定义一个双端队列
queue,用于存放滑动窗口中的数在nums中的下标 - 依次遍历数组
nums中的每个值 - 当队尾元素指向的值小于即将入队的值时,将队尾元素从队尾弹出
- 重复步骤 3,直到队列为空或者队尾元素指向的值大于即将入队的值
- 将即将入队的值的下标入队
- 判断队首的元素下标是否应该在当前的滑动窗口中,即
队首的下标 + k <= 新入队的下标 i则表示队首的下标已经不在当前的滑动窗口中,应该将当前下标从队列中出队 - 此时在队列中队首存放的下标即为当前窗口最大值的下标,因为从开始遍历到第
k个值之后才需要输出窗口的最大值,因此还需要将当前入队的下标与k值作比较,符合条件的才将队首存放下标指向的值插入到结果数组中
解题代码
var maxSlidingWindow = function(nums, k) {
const ans = []
const queue = []
let i = 0
while (i < nums.length) {
while (queue.length && nums[queue[queue.length - 1]] <= nums[i]) {
queue.pop()
}
queue.push(i)
if (queue.length && queue[0] + k <= i) {
queue.shift()
}
i++
if (i >= k) ans.push(nums[queue[0]])
}
return ans
};