单调栈的四种用法

单调栈主要用于解决 Next Greater Element 问题,即找左边/右边第一个比自己小/大的元素(位置)。

以下是对四种问题的实现。

Copy
#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]) { // 此时栈中凡是比当前元素小的,那么它右边第一个比自己大的元素位置都是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; }
posted @   Nepenthe8  阅读(227)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示