7.239. 滑动窗口最大值

思路:

单调队列(用deque实现)

一开始看到滑动窗口,想到之前写过的滑动窗口的题

5.209.长度最小的子数组-优快云博客

但是发现滑动窗口没法直接用(要维护滑动窗口里的最大值)

那道题要维护的条件是滑动窗口里的数组和,只需要用数组就行了。这道题要维护最大值,就要用高级点的数据结构才方便点,简单用数组不好解决。滑动窗口最大值是单调队列的经典应用。

储备:

代码随想录

单调队列顾名思义就是单调的队列,和优先级队列的区别是单调队列只用维护最值。弹出去的不用管,不用维护整个窗口单调。

单调队列是用双端队列实现的。实际上c++栈stack和队列queue底层都是用双端队列形成的。双端队列两段皆可插入,两段皆可删除。稍微改一下就能变成栈和队列。代码随想录

问题:

1、写一个新类的格式,类最后要加“;”

class myqueue {
public:
    deque<int> que;

    void push(int k) {//主体一步。一个while维护单调性,弹出队尾
        while (!que.empty() && que.back()<k) {
            que.pop_back();
        }
        que.push_back(k);//插入窗口头
    }

    void pop(int k) {//一步。一个if弹出队头。
        if (!que.empty() && que.front()==k) {
            que.pop_front();
        }
    }

    int front() {//一步,直接返回
        return que.front();
    }
};

2、为什么pop里的条件是que.front()==k?

因为应用场景是滑动窗口。滑动窗口的最左端和单调队列的队头要区分开。只有当滑动窗口的最左端是单调队列的队头时才需要弹出,不然就留在队列里。没弹出可以是两种情况,一种是作为最大值一直留着,存入res返回值。一种是作为最大值替补,当最大值弹出后补上去。

那会一直留在队列里,最后误记录吗?

不会。因为会弹出操作里有当最大值是滑动窗口最左端该弹出时,会弹出。弹出后再记录结果返回值。

for (int i=k;i<n;i++) {
            que.push(nums[i]);
            que.pop(nums[i-k]);
            res.push_back(que.front());
        }

最后:

class myqueue {
public:
    deque<int> que;

    void push(int k) {//主体一步。一个while维护单调性,弹出队尾
        while (!que.empty() && que.back()<k) {
            que.pop_back();
        }
        que.push_back(k);//插入窗口头
    }

    void pop(int k) {//一步。一个if弹出队头。
        if (!que.empty() && que.front()==k) {
            que.pop_front();
        }
    }

    int front() {//一步,直接返回
        return que.front();
    }
};

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        myqueue que;
        vector<int> res;
        int n = nums.size();
        for (int i=0;i<k;i++) {
            que.push(nums[i]);
        }
        res.push_back(que.front());
        for (int i=k;i<n;i++) {//一步。用单调队列维护滑动窗口最值即可。
            que.push(nums[i]);
            que.pop(nums[i-k]);
            res.push_back(que.front());
        }
        return res;
    }
};

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值