单调栈

从栈底到栈顶,元素的值单调增加(递增栈)或单调减小(递减栈),多用于求解左右大小边界问题

  1. 向左找第一个比自身大的数
  2. 向左找第一个比自身小的数
  3. 向右找第一个比自身大的数
  4. 向右找第一个比自身小的数

概念

维护单调栈:只需要将要入栈的数据和栈顶比较
1. 若符合条件,直接入栈
2. 若不符合条件,将栈顶出栈,直到符合条件为止

用单调栈解决左右大小边界问题两种思路

栈顶为答案

找左边第一个比自己大的数

  • 从左到右遍历,用递减栈保存已经遍历过的数
  • a[i]符合入栈条件时栈不为空,则第一个比a[i]大的数就是此时栈顶元素
  • a[i]符合入栈条件时栈为空,说明a[i]左边没有比a[i]大的数
  • 不符合入栈条件就连续出栈栈顶元素,直到符合入栈条件

由于出栈的数都是比后面的要入栈数小,所以一定不符合要找的第一个比自己大的数条件,不会漏掉答案

模板

#include <iostream>  
#include <stack>  
  
using namespace std;  
  
//向左找第一个比自己大的数  
  
int n;    //n<=100  
int a[105];  
int ans[105];    //答案数组  
stack<int> s;  
  
int main() {  
    cin >> n;  
    for (int i = 1; i <= n; i++) {  
       cin >> a[i];  
    }  
    for (int i = 1; i <= n; i++) {  
       while (!s.empty() && s.top() <= a[i])s.pop();  
       if (s.empty())ans[i] = -1;    //表示左边没有比a[i]大的数  
       else {  
          ans[i] = s.top();  
       }  
       s.push(a[i]);  
    }  
    //输出答案  
    for (int i = 1; i <= n; i++) {  
       cout << ans[i] << " ";  
    }  
    cout << endl;  
    return 0;  
}

找左边第一个比自己小的数

  • 从左到右遍历,用递增栈保存已经遍历过的数
  • a[i]符合入栈条件时栈不为空,则第一个比a[i]小的数就是此时栈顶元素
  • a[i]符合入栈条件时栈为空,说明a[i]左边没有比a[i]小的数
  • 不符合入栈条件就连续出栈栈顶元素,直到符合入栈条件

找右边第一个比自己大的数

  • 从右到左遍历,用递减栈保存已经遍历的数
  • a[i]符合入栈条件时栈不为空,则第一个比a[i]大的数就是此时栈顶元素
  • a[i]符合入栈条件时栈为空,说明a[i]左边没有比a[i]大的数
  • 不符合入栈条件就连续出栈栈顶元素,直到符合入栈条件

找右边第一个比自己小的数

  • 从右到左遍历,用递增栈保存已经遍历的数
  • a[i]符合入栈条件时栈不为空,则第一个比a[i]小的数就是此时栈顶元素
  • a[i]符合入栈条件时栈为空,说明a[i]左边没有比a[i]小的数
  • 不符合入栈条件就连续出栈栈顶元素,直到符合入栈条件

当前遍历到的数为答案

找左边第一个比自己大的数

  • 从右到左遍历,用递减栈存已经遍历的数
  • a[i]符合入栈条件直接入栈
  • a[i]不符合入栈条件,说明此时要出栈的栈顶元素的答案就是此时的a[i]
  • 遍历完所有数后,若栈非空,栈中的所有元素没有答案

模板

#include <iostream>  
#include <stack>  
  
using namespace std;  
  
//找左边第一个比自己大的数  
  
int n;    //n<=100  
int a[105];  
int ans[105];  
stack<int> s;  
  
int main() {  
    cin >> n;  
    for (int i = 1; i <= n; i++) {  
       cin >> a[i];  
    }  
    for (int i = n; i >= 1; i--) {  
       while (!s.empty() && a[s.top()] < a[i]) {  
          ans[s.top()] = a[i];  
          s.pop();  
       }  
       s.push(i);    //入栈下标  
    }  
    while (!s.empty()) {  
       ans[s.top()] = -1;  
       s.pop();  
    }  
    for (int i = 1; i <= n; i++) {  
       cout << ans[i] << " ";  
    }  
    cout << endl;  
    return 0;  
}
  • 其他三种同理
posted @ 2026-04-04 09:28  mofei1116  阅读(11)  评论(0)    收藏  举报