这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位,返回滑动窗口中的最大值。
单调队列
首先队列里的元素一定是要排序的,而且要最大值放在出队口,要不然怎么知道最大值呢。 但如果把窗口里的元素都放进队列里,窗口移动的时候,队列需要弹出元素。 那么问题来了,已经排序之后的队列 怎么能把窗口要移除的元素(这个元素可不一定是最大值)弹出呢。
其实队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队里里的元素数值是由大到小的。
那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。JS中没有直接支持单调队列,需要我们自己来一个单调队列
不要以为实现的单调队列就是 对窗口里面的数进行排序,如果排序的话,那和优先级队列又有什么区别了呢。
题解
创建队列q,存放的是nums的下标i 窗口初始化时,将最初的k个元素的下标入队,并要保证对应的值是依次递减的,若前一个值小于后一个值,则将前一个值下标弹出 这样就可以保证,q的队头元素对应的值,肯定是初始窗口中最大的 窗口开始滑动,做之前相同的操作。还要将窗口外的值下标弹出队列 每次滑动,取出队头下标对应的值即可
var maxSlidingWindow = function(nums, k) {
// 存取队列 (存放元素下标)
const q = [];
// 存取结果
const ans = [];
for (let i = 0; i < nums.length; i++) {
while (q.length && nums[i] >= nums[q[q.length - 1]]) {
q.pop()
}
// 入队当前元素下标
q.push(i);
// 判断当前最大值(即队首元素)是否在窗口中,若不在便将其出队
while (q[0] <= i - k) {
q.shift();
}
// 当达到窗口大小时便开始向结果中添加数据
if (i >= k - 1) ans.push(nums[q[0]])
}
return ans;
};