1.什么是单调栈?有什么好处?
定义: 单调栈就是栈内元素递增或者单调递减的栈,并且只能在栈顶操作。单调栈的维护是O(n)的时间复杂度,所有元素只会进进栈一次
见名知意,就是栈中元素,按递增顺序或者递减顺序排列的时候
单调栈的最大好处就是时间复杂度是线性的,每个元素遍历一次!
2.哪些性质?
上代码:
public void doStack(int[] nums) {
Stack stack = new Stack<>();
for(int i=0;i
结果:
[3]
[3, 5]
[3, 4]
[1]
比如数组:[3,5,4,1],我们如何要找每一个元素下一个最小数.例如:3 下一个最小的数为1,5下一个是4.我们先构造栈,把3压入栈中,5入栈时候,发现栈顶元素3比它小,也依次压入;当4时候,栈顶元素5大于4,于是得到,5左起第一个小的元素为4.将5弹出,压入4.接下来元素1,也比栈顶元素小,于是得到4第一个小的元素为1,弹出4,依次类推,3也是1...栈中的元素一直保持单调递增的状态.
五分钟算法有个视频,也可以戳进去看看。
- 单调递增栈可以找到左起第一个比当前数字小的元素,栈中的元素一直保持单调递增的状态。
- 单调递减栈可以找到左起第一个比当前数字大的元素
(此处应有黑人问号??)
LeetCode:503 下一个更大元素:
- 题目是单调递减栈,又是循环数组,需要我们copy一份数组;
- 栈中保存数组的下标;
- 栈顶的元素就是我们要找的值的数组下标;
talk is cheap,show you the code:
public int[] nextGreaterElements(int[] nums) {
int[] result = new int[nums.length];
Arrays.fill(result,-1);
int n = nums.length;
Stack stack = new Stack<>();
for(int i=0;i nums[stack.peek()]) {
result[stack.pop()]= nums[i%n];
}
if(i
绝妙的操作,哈哈哈。酒馆的鲍勃太洗脑了。
这块开始我也不是很理解,摘抄一下大佬写的解释,慢慢体会,你细品♂️
我们维护一个递减的stack,stack内部存的是数组的每个index,当我们遇到一个比当前栈顶对应的数大的数的时候。我们称遇到了一个“大数”,这个大数多大,我们不知道,至少比当前栈顶对应的数大,我们弹出栈内所有对应数比这个数小的栈内元素,并更新它们在返回数组中对应位置的值。因为这个栈具有单调性,当我们栈顶元素所对应的数比这个元素大的时候,我们可以保证,栈内所有元素都比这个元素大,对于每一个元素,当它出栈时,说明遇到了自己的next greater element,我们更新return数组中的对应位置的值。对于一个元素不曾出栈,说明不存在greater elment,我们也就不用更新return数组了。
我们试试调用栈能不能解决一些NB一点的问题,看看下面这个:
- 题目中要求的是最大面积,不就是奥卡姆提高原理。面积最大决定最短的板有多短。。我们需要构造单调递增栈,如果遇到第一个比遍历元素小的柱子,我们就操作。
(1) 为了处理方便,给height数组前后各加了一个0,确保了单调增栈有效。
(1)注意算面积的时候,左右边界的索引,做边界其实是出栈之后栈顶的值,再减一。不是i-index。你细品。=。=(学坏了,如果i-index只能过一半的用例)
public int largestRectangleArea(int[] heights) {
Stack stack = new Stack<>();
int result = 0;
int[] newHeight = new int[heights.length + 2];
newHeight[0] = 0;
for(int i =0;i< heights.length;i++) {
newHeight[i+1] = heights[i];
}
newHeight[heights.length + 1] = 0;
for (int i = 0; i < newHeight.length; i++) {
while (!stack.isEmpty() && newHeight[i] < newHeight[stack.peek()]) {
int index = stack.pop();
// 面积:前一个的高度 *( 现在的位置-前一个高度索引-1)
result = Math.max(result, newHeight[index]*(i-stack.peek()-1));
}
stack.push(i);
}
return result;
}
下面这个是送分题了吧,=。=,是不是应该感叹出题人真无聊
单调减栈,按要求的输出即可
public int[] dailyTemperatures(int[] T) {
int[] result = new int[T.length];
Arrays.fill(result, 0);
Stack stack = new Stack<>();
for (int i = 0; i < T.length; i++) {
while (!stack.isEmpty() && T[i] > T[stack.peek()]) {
int index = stack.pop();
result[index] = i - index;
}
stack.push(i);
}
return result;
}
还有个水滴,作为思考题吧,以后再刷=。=