单调栈
一维数组,单调栈可以一次遍历就能够求得一个元素左右两边第一个比自己大或者小的元素的位置
tips:
如果求每个元素左右两边第一个比自己小的元素,通过给原始数组的头尾添加0,可以一次遍历栈中元素就能全部弹出,得到原来每个元素的左右两边第一个比自己小的元素。求左右两边第一个比自己大的元素类似,可以在头尾添加Integer.MAX_VALUE。
当我们遍历到一个位置i需要寻找数组中左边或者右边的所有数字和 nums[i]nums[i] 的大小关系的题目,可以考虑一下单调栈。
第一个比自己大的元素:
- 单调递增(从栈顶向栈底看)
- 遍历的当前元素若大于栈顶元素,一直弹出栈顶元素,直到栈为空或不再大于栈顶元素。对于弹出的元素来说,当前元素是他第一个比自己大的元素。
- 遍历的当前元素若小于等于栈顶元素,压入栈。
第一个比自己小的元素:单调递减(从栈顶向栈底看)
- 单调递减(从栈顶向栈底看)
- 遍历的当前元素若小于栈顶元素,一直弹出栈顶元素,直到栈为空或不再小于栈顶元素。对于弹出的元素来说,当前元素是他第一个比自己小的元素。
- 遍历的当前元素若大于等于栈顶元素,压入栈。
题目总结
第一个比自己大(小)的元素
-
AAAA6080. 使数组按非递减顺序排列
一个元素经过多少次操作才能被移除取决于它与左侧第一个大于它的元素之间的元素,等于这些元素最大操作次数的再加1。意思就是说,只有那个需要最大操作次数的中间元素被移除之后,当前元素才有能被左侧第一个大于它的元素移除。 -
AAAA456. 132 模式
寻找所有一侧比当前元素小的元素,然后去做判断。 -
0AAAA907. 子数组的最小值之和
寻找左右两侧比自己小的下标(边界),确定以当前值作为最小值的子数组的个数,注意相同的数字要避免重复计算子数组个数。
括号序列相关
- AAAA1190. 反转每对括号间的子串
遇到’)‘就弹出字符知道遇到’(',遇到其他就一直压入栈。 - AAAA856. 括号的分数
同级相加,嵌套乘以2.用栈区分平级还是嵌套的关系。
约减数量
- 0AAAA862. 和至少为 K 的最短子数组
单调栈过滤掉不可能的,多余的前缀和,从而降低时间复杂度。