单调队列&单调栈
单调队列
原理
普通队列就如果食堂打饭一样,先进先出,而单调队列的元素具有单调性(递增或者递减),在保持元素进出的相对顺序不变,维持了大小顺序。如排队过程中突然有个人高马大的小伙过来,来到队尾看到别人比他矮好欺负,把别人赶走,一旦打不过别人就乖乖排队。

如上图,原始数据为 ,添加 6 后单调递增队列为 现在添加 2 到队尾,单调队列弹出比 2 大的数,并加入 2 后变为
应用
可用于求解滑动窗口最值问题,如下面 leetcode 问题。

思路:维持一个单调递减队列,记录各个元素的位置(下标),队首元素就是窗口最大值的下标,窗口在滑动过程中,不属于窗口的元素从队首弹出,而队尾在满足单调队列的性质下加入当前元素。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.empty()) return {};
deque<int>dq;
for (int i = 0; i < k; ++i) {
while (!dq.empty() && nums[i] > nums[dq.back()]) {
dq.pop_back();
}
dq.push_back(i);
}
int n = nums.size();
vector<int>res(n - k + 1);
res[0] = nums[dq.front()];
for (int i = k; i < n; ++i) {
while (!dq.empty() && nums[i] > nums[dq.back()]) {
dq.pop_back();
}
dq.push_back(i);
while (dq.front() <= i - k) {
dq.pop_front();
}
res[i - k + 1] = nums[dq.front()];
}
return res;
}
};
单调栈
和单调队列类似,不同的是满足元素后进先出。主要处理一下几种问题:
-
比当前元素更大的下一个元素
-
比当前元素更大的前一个元素
-
比当前元素更小的下一个元素
-
比当前元素更小的前一个元素
可通过单调递增/递减栈,外加遍历顺序(顺序,逆序)实现以上功能。
问题


因为问的是后面哪天比今天温度高,所以从后往前遍历。
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
if(temperatures.empty()) return {};
int n = temperatures.size();
stack<int>stk;
vector<int>res(n);
for(int i = n-1; i >=0; --i){
while(!stk.empty() && temperatures[i] >= temperatures[stk.top()]){
stk.pop();
}
if(stk.empty()) res[i] = 0;
else{
res[i] = stk.top() - i;
}
stk.push(i);
}
return res;
}
};
总结
无论单调栈还是单调队列,比较队尾元素和新的待加入元素,是否能取到等号需要根据具体问题来确定,想像取到等号对问题的解答是否有影响。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律