单调栈
单调栈
从名字上就听的出来,单调栈中存放的数据应该是有序的,所以单调栈也分为单调递增栈和单调递减栈
- 单调递增栈:(上面元素是最小元素) 单调递增栈就是从栈底到栈顶数据是从大到小
- 单调递减栈:(上面元素是最大元素) 单调递减栈就是从栈底到栈顶数据是从小到大
应用题目1
1.视野总和
描叙:有n个人站队,所有的人全部向右看,个子高的可以看到个子低的发型,给出每个人的身高,问所有人能看到其他人发现总和是多少。
输入:4 3 7 1
输出:2
==转换:从后向前遍历,计算所有元素与上一个比它大的元素的间隔之和==
1 |
应用题目2
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
输入: [2,1,5,6,2,3]
输出: 10
单调栈用法:
官方给出的题解是利用单调栈计算出每个点展开左右边界,保存在了left和right中 (我自己写时,也想到这个问题,不过没有采用合适的数据结构vector,而是采用栈–自己之所以采用栈是为了配合单调栈,但其实是每个结点都需要保存他的左右边界)
如何确定左右边界
单调栈中保存从左到右遍历 递增序列的index 每个结点的左边界为栈中相邻+靠栈低的元素(从左遍历,最近的且小于该处高度的点) 单调栈保存index
结点的右边界为 右侧第一个小于当前高度的索引,所以最开始入栈时,是不确定的
确定某个左右边界的时间:
- 右边界 当结点从单调栈中弹出时,计算它的右边界。 按照单调栈的结构,当结点遇到第一个比它高度小的结点,该结点就会被弹出。这就是它的右边界,如果遍历完数组,仍在栈中,默认右边界为n
- 左边界 当结点压入栈中时,计算它的左边界。 左边界为当前栈顶元素,如果栈为空则是-1 再把该节点的index压入栈
1 | class Solution { |
应用题目3
456. 132 模式
给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。
如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/132-pattern
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1 | class Solution { |
递减栈(栈顶保存最小的元素)
回顾本题解决思路
寻找是否有132模式
从右到左进行遍历
我们希望确定3之后,2是3右侧小于3的最大的数,方便更好地判断 1是否存在。
- 如何确定
32
结构
从右到左遍历
这里利用递减栈可以 保存当前值 距离 右侧第一个大于它的数 之间,最大的那个元素(保存在max_k中)
即维护递减栈过程中,更新当前pop的最大值
- 何时确定?
- 确定32结构:
遍历栈时,如果有nums[i]>item.top(),更新max_k,保存最新的32结构
- 要一开始就判断是否存在 1
如果nums[i] <max_k ,则一定存在132模式
- 确定32结构: