LeetCode刷题指北----单调栈

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;
    }

还有个水滴,作为思考题吧,以后再刷=。=

你可能感兴趣的:(LeetCode刷题指北----单调栈)