单调栈思想及其应用
单调栈,顾名思义就是栈内元素单调排列的栈,分为单调递增栈和单调递减栈。
单调递增栈:从栈底到栈顶,元素从大到小排列;即元素出栈序列为单调递增的。
单调递减栈:从栈底到栈顶,元素从小到大排列;即元素出栈序列为单调递减的。
常见作用:
在数组(数字序列)中为任意一个元素,找 左/右 边第一个比自己 大/小 的元素。
算法步骤:
例如:序列 3 4 2 7 5 ,输出每一个元素左边第一个比它小的数字(没有则输出-1)。
寻找前一个更小的元素,使用单调递减栈。
一开始,输出-1,3 入栈,;栈状态:3
然后 4 和栈顶 3 对比,发现 4 > 3 ,输出 3,4 入栈;栈状态:3 4
然后 2 和栈顶 4 对比,发现 2 < 4 ,想找到比 2 小的元素,所以需要不断弹栈,弹出栈顶元素;所以 4 弹栈,3 弹栈,栈为空,输出-1,2 入栈;栈状态:2
然后 7 和栈顶 2 对比,发现 7 > 2 ,输出 2,7 入栈;栈状态:2 7
最后 5 和栈顶 7 对比,发现 5 < 7,7 弹栈,找到 2 比 5 小,输出 2 ,5 入栈;栈状态:2 5
所以答案为 -1,3,-1,2,2
题目:

实现代码:
#include<iostream> using namespace std; int main(){//单调栈思想,边读入边做单调栈,栈顶元素表示该栈最大元素,若当前读入元素小于等于栈顶元素 //栈顶元素没用了,因为相对于后面的读入,当前元素是更好的选择,因此栈顶弹栈,直到在栈内找到小于当前元素的,输出 //或者找不到输出-1,最后把当前元素加入栈顶 int n; int *stk=new int[n]; int num; int st=0;//本st表示栈内元素个数 cin>>n; for(int i=0;i<n;i++){ cin>>num; while(st&&stk[st-1]>=num)st--; if(st)cout<<stk[st-1]<<" "; else cout<<"-1 "; stk[st++]=num; } return 0; }
我也总结了向左/右寻找下一个更大/小元素的做法:
左边第一个更小:单调递减栈,顺序遍历(同上例题)
左边第一个更大:单调递增栈,顺序遍历
右边第一个更小:单调递减栈,逆序遍历
右边第一个更大:单调递增栈,逆序遍历
力扣经典单调栈题目:
503. 下一个更大元素 II - 力扣(LeetCode)

浙公网安备 33010602011771号