[路飞]_队列之单调队列

116 阅读1分钟

239. 滑动窗口最大值

题目很明确的表明了,维护一个滑动窗口,在这个滑动窗口每次移动中获取其中的最大值


那怎么维护一个滑动窗口呢,又能保证每次能获取其中的最大值,那就只有具有单调性的队列


单调性只有两种,要么单调递增,要么单调递减, 既然获取的是最大值,那就维护单调递减的队列即可


实现代码如下,解法一,解法二:只是在队列存储的元素不同,本质是一样的


解法一

var maxSlidingWindow = function (nums, k) {
    let result = []
    let dequeue = [] //单调队列
    
    for(let i = 0; i < nums.length; i++){
        // 当窗口滑动时,检查单调队列队首元素是否不在窗口中,若不在窗口中则将其移除
        if(nums[i -k] === dequeue[0]){
            dequeue.shift()
        }
        // 如果队列中有值,则将队列中所有比当前num[i]小的值清空,保证队列的单调递减性
        while(dequeue.length && nums[i] > dequeue[dequeue.length -1]){
            dequeue.pop()
        }
        // 将新进入窗口的元素推入队列中
        dequeue.push(nums[i])
        // 当窗口被填满后,在开始往result添加需要的元素
        if(i >= k -1){
            // 由于队列是单调递减的,所以队列中第一个元素即是最大值
            result.push(dequeue[0])
        }
    }
    return result
};


解法二

var maxSlidingWindow = function (nums, k) {
    let result = []
    let dequeue = [] //单调队列
    
    for(let i = 0; i < nums.length; i++){
        while( dequeue.length && nums[dequeue[dequeue.length -1]] < nums[i]){
            dequeue.pop()
        }
        // 在队列中加入的是元素的下标
        dequeue.push(i)
        if( i - dequeue[0] === k){
            dequeue.shift()
        }
        if(i + 1 < k){
            continue;
        }
        result.push(nums[dequeue[0]])
    }
    return result
};