单调栈的四种用法

单调栈主要用于解决 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]) { // 此时栈中凡是比当前元素小的,那么它右边第一个比自己大的元素位置都是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 @ 2022-03-05 14:40  Nepenthe8  阅读(140)  评论(0编辑  收藏  举报