239. 滑动窗口最大值

243 阅读3分钟

239. 滑动窗口最大值

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

给你一个整数数组 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

具体题目链接: 题目链接

思路:

思路:滑动窗口思路

窗口扩展时寻找可行解,窗口收缩时优化可行解

当滑动窗口可以定长时,一直维护k个长度的滑动窗口即可

当滑动窗口需要不定长时,需要通过特定条件(比如滑动窗口的总和)来判断left和right指针 到底是移动哪个

分析:

// 目标维护一个单调递减的滑动窗口(保证队头都是最大值,用下标区控制长度)
//这题是定长滑动
//什么情况往右移(也就是右边增加元素)->当待添加元素大于队列末端元素,这是为了保证单调递减
// 到了临界点应该怎么更新->结果上一步处理 之后再添加元素
//什么时候left右移(由于是定长,右边先移动定长数量比如k个,然后左右是同时移动)
//应该怎么更新(判断条件在left++)
//本题是1.超过k个就每次移动保存一下(判断一次应该用if,判断多次要用while)
//2.下标显示队列有超过3个就把最先进去的删掉
// 返回res

代码:

var maxSlidingWindow = function(nums, k) {
    let s = nums;
    let res = [];
    let qu = [];//队列,里面存的是下标
    let i = 0;
    while(i<s.length) {
    // for(let i=0;i<s.length;i++) {//循环枚举所有数组元素s[i]的下标i
        while(qu.length && s[i]>=s[qu[qu.length-1]]) { //为了维护一个单调递减队列,队列不空且待添加的元素值大于队列已有的队尾值,就(1)删完之后,执行(2)
            qu.pop();//(1)就将队尾值删掉
        }
        //首先执行这一句
        qu.push(i);//(2)待添加的元素值

        if(qu.length && qu[0]<i-k+1) {// /队列不空且当前枚举到的元素下标i与队首(下标)之差大于窗口长度,只能存k个值,多余的就弹出去
            qu.shift();//窗口向右滑动,队头出队;
        }

        if(i-k+1>=0) {//因为这里是下标i=0开始,枚举到第k-1个元素后,每次枚举一个新的i都要找一次答案
            res.push(s[qu[0]]);//维护的是递减队列 所以对头的元素最大,将队列当前队首下标对应的元素加入到答案数组
        }

        i++;
    }
    return res;//返回一个答案数组
};

总结:

这是算法系列文章「滑动窗口」的相关题解

类型滑动窗口类型题目,解题方法窗口扩展时寻找可行解,窗口收缩时优化可行解