单调栈和单调队列
单调栈
单调栈:栈中的数据是单调的(单调增或单调减),只能入栈、出栈操作。单调栈一个常见的应用是:在我们维护栈的有序性时,在进行入栈出栈操作时会做一些额外的逻辑计算。
例题
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0, n = height.size();
stack<int> stk;
for (int i = 0; i < n; ++i) {
// 找到第一个大于栈顶的值,然后开始出栈.
while (!stk.empty() && height[i] > height[stk.top()]) {
//std::cout << "----here----\n";
int top = stk.top();
stk.pop();
if (stk.empty()) {
break;
}
int left = stk.top(); // 这里的left = 被pop元素的前一个
int currWidth = i - left - 1;
int currHeight = min(height[left], height[i]) - height[top];
ans += currWidth * currHeight;
}
stk.push(i);
}
return ans;
}
};
单调队列
单调队列定义:队列中的数据是单调的(单调递增或递减),只能从队头或队尾操纵数据。单调队列在一下情况适用(待补充):
- 固定区间内的最大值/最小值,即和滑动窗口类似
例题
#include <algorithm>
#include <deque>
#include <vector>
#include <cassert>
std::vector<int> slideWindow(std::vector<int> inputData, windowLen) {
auto size = inputData.size();
assert(size >= windowLen);
std::deque<int> que;
// init
for (int i = 0; i < windowLen; ++i) {
// 保证队列单调递减,inputData[que.front()] is maximum
while(!que.empty() && inputData[i] >= inputData[que.back()]) {
que.pop_back();
}
que.push_back(i);
}
std::vector<int> ans;
ans.reserve(size - windowLen + 1); // 预留size - windowLen + 1个位置(固定),见注释代码
ans.emplace_back(inputData[que.front()]);
for (int i = windowLen; i < size; ++i) {
while(!que.empty() && inputData[i] >= inputData[que.back()]) {
que.pop_back();
}
que.push_back(i);
// 剔除窗口外的数据
while(que.front() <= i - k) {
que.pop_front();
}
ans.emplace_back(inputData[que.front()]);
}
/*
std::vector<int> ans(size - windowLen + 1, 0);
int pos{0};
ans[pos++] = inputData[que.front()];
for (int i = windowLen; i < size; ++i) {
while(!que.empty() && inputData[i] >= inputData[que.back()]) {
que.pop_back();
}
que.push_back(i);
// 剔除窗口外的数据
while(que.front() <= i - k) {
que.pop_front();
}
ans[pos++] = inputData[que.front()];
}
*/
return ans;
}