单调栈
什么的单调栈?
单调栈就是栈里面存放的数据都是有序的,所以可以分为单调递增栈和单调递减栈两种。
- 单调递增栈就是从栈底到栈顶是从大到小
- 单调递减栈就是从栈底到栈顶是从小到大
为什么要使用单调栈?
这个问题应该就是大家的一个共同问题了吧,why?其实很简单就拿LeetCode503. 下一个更大元素 II
这道题来讲,如果利用常规解法,对于每个数而言,我们需要遍历其右边的数,直到找到比自身大的数,这是一个 O(n^2) 的做法。之所以是 O(n^2),是因为每次找下一个最大值,我们是通过遍历来实现的。如果面试的时候遇到这个问题了你采用常规解法可能你就gg了。而使用单调栈的话你就可以将复杂度降到O(n),这就是你为啥要使用单调栈的原因了,原因就是为了混口饭吃!!!
什么时候使用单调栈?
问题又来了啥时候使用呢?一般来讲,【找左右两边比你大或者比你小】的问题,都可以使用单调栈来解决。所以遇到这种问题一定要记得单调栈。单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录左(右)边第一个比当前元素大(小)的元素,优点是只需要遍历一次。
在使用单调栈的时候首先要明确如下几点:
单调栈里存放的元素是什么?
单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接用 nums[i] 就可以获取
基本模板
只需要改变其中一些符号还有定义
public int[] monostoneStack(int[] arr) {
stack 定义栈
int []ans = 定义一个长度和 arr 一样长的数组,并初始化为合适的值
循环i 到 arr {
while (stack非空 and (arr[当前元素]与arr[栈顶元素]作比较))
preIndex= 弹出栈顶元素
ans[preIndex] = i - preIndex
或者说ans[preIndex]=arr[当前元素]
stack.push(i) 压入当前元素
}
return ans;
}
举例
[503. 下一个更大元素 II].
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素