思路:
单调队列(用deque实现)
一开始看到滑动窗口,想到之前写过的滑动窗口的题
但是发现滑动窗口没法直接用(要维护滑动窗口里的最大值)
那道题要维护的条件是滑动窗口里的数组和,只需要用数组就行了。这道题要维护最大值,就要用高级点的数据结构才方便点,简单用数组不好解决。滑动窗口最大值是单调队列的经典应用。
储备:
单调队列顾名思义就是单调的队列,和优先级队列的区别是单调队列只用维护最值。弹出去的不用管,不用维护整个窗口单调。
单调队列是用双端队列实现的。实际上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;
}
};

368

被折叠的 条评论
为什么被折叠?



