单调栈主要用于解决 Next Greater Element 问题,即找左边/右边第一个比自己小/大的元素(位置)。
以下是对四种问题的实现。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
// 0 1 2 3 4 5
vector<int> t = {4, 2, 3, 3, 5, 4};
int n = (int)t.size();
vector<vector<int>> a(4);
for (int i = 0; i < 4; i++) {
a[i] = t;
}
vector<vector<int>> ans(4, vector<int>(n, -1));
vector<stack<int>> stk(4);
// 找右边第一个比自己大的元素位置(0-index)
// 输出应为 {4, 2, 4, 4, -1, -1},其中 -1 代表不存在
// 栈自底向上单调递减(很容易从弹栈的条件看出来,栈顶需要大于等于带加入元素,因而是递减
for (int i = 0; i < n; i++) {
while (!stk[0].empty() && a[0][stk[0].top()] < a[0][i]) {
ans[0][stk[0].top()] = i;
stk[0].pop();
}
stk[0].push(i);
}
for (int i = 0; i < n; i++) {
cout << ans[0][i] << " \n"[i == n - 1];
}
// 找右边第一个比自己小的元素位置(0-index)
// 输出应为 {1, -1, -1, -1, 5, -1}
// 栈自底向上单调递增
for (int i = 0; i < n; i++) {
while (!stk[1].empty() && a[1][stk[1].top()] > a[1][i]) {
ans[1][stk[1].top()] = i;
stk[1].pop();
}
stk[1].push(i);
}
for (int i = 0; i < n; i++) {
cout << ans[1][i] << " \n"[i == n - 1];
}
// 找左边第一个比自己大的元素位置(0-index)
// 输出应为 {-1, 0, 0, 0, -1, 4}
// 栈自底向上严格单调递减
for (int i = 0; i < n; i++) {
while (!stk[2].empty() && a[2][stk[2].top()] <= a[2][i]) {
stk[2].pop();
}
if (!stk[2].empty()) {
ans[2][i] = stk[2].top();
}
stk[2].push(i);
}
for (int i = 0; i < n; i++) {
cout << ans[2][i] << " \n"[i == n - 1];
}
// 找左边第一个比自己小的元素位置(0-index)
// 输出应为 {-1, -1, 1, 1, 3, 3}
// 栈自底向上严格单调递增
for (int i = 0; i < n; i++) {
while (!stk[3].empty() && a[3][stk[3].top()] >= a[3][i]) {
stk[3].pop();
}
if (!stk[3].empty()) {
ans[3][i] = stk[3].top();
}
stk[3].push(i);
}
for (int i = 0; i < n; i++) {
cout << ans[3][i] << " \n"[i == n - 1];
}
return 0;
}