初始化栈的代码_单调栈算法

一、单调栈的概念

从栈底元素到栈顶元素呈单调递增或单调递减,栈内序列满足单调性的栈。

二、单调栈算法举例

LeetCode_84柱状图中最大的矩形(https://leetcode-cn.com/problems/largest-rectangle-in-histogram/)

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

以下是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

示例:
输入: [2,1,5,6,2,3]
输出: 10

3d0b6cf33736ea97d0195bf4c0860e39.png

按照单调栈的思路,递增时入栈,其余时计算面积并出栈,直到继续递增时入栈。面积将通过计算当前位置和栈顶元素所在位置的宽度查,再乘上元素的height值的思路来做这题:

class Solution {
    public int largestRectangleArea(int[] heights) {
        // 两个栈,一个存位置,一个存值
        Stack<Integer> posStack = new Stack<>();
        Stack<Integer> valueStack = new Stack<>();
        posStack.push(-1);
        valueStack.push(-1);

        int maxArea = 0;

        for (int i = 0; i <= heights.length; i++) {
            // 当前值比栈顶大,即压栈
            if (i < heights.length && heights[i] >= valueStack.peek()) {
                posStack.push(i);
                valueStack.push(heights[i]);
            }
            else {
                // 已到头了,挨个向前把每个面积都算一下
                if (i >= heights.length) {
                    while (posStack.peek() != -1) {
                        int value = valueStack.peek();
                        valueStack.pop();
                        posStack.pop();
                        int area = value * (i - posStack.peek() - 1);
                        maxArea = area > maxArea ? area : maxArea;
                    }
                }
                // 未到头时,当前值比栈顶小的,则向前计算面积,直到比栈顶大,压栈
                else {
                    while (heights[i] < valueStack.peek()) {
                        int value = valueStack.peek();
                        valueStack.pop();
                        posStack.pop();
                        int area = value * (i - posStack.peek() - 1);
                        maxArea = area > maxArea ? area : maxArea;
                    }
                    posStack.push(i);
                    valueStack.push(heights[i]);
                }
            }
        }
        return maxArea;
    }

}

这道题说起来花了不少时间,从理解思路,到实际写代码,写代码时有两个用例又没通过,再重新调试对了思路。直到最后现在的结果。

21cca915b6d2e64896d565a27a9c0b8a.png

其实可以做一些代码优化,少一个栈空间,代码做下抽去方法的精简,但其实我觉得没太大的必要,可以看下优化的:

class Solution {
    public int largestRectangleArea(int[] heights) {
        // 初始化栈,存位置-1,压底
        Stack<Integer> posStack = new Stack<>();
        posStack.push(-1);
        // 最大面积
        int maxArea = 0;

        for (int i = 0; i <= heights.length; i++) {
            // 当前值比栈顶大,即压栈
            if (i < heights.length && heights[i] >= (posStack.peek() == -1 ? -1 : heights[posStack.peek()])) {
                posStack.push(i);
            }
            else {
                // 已到头了,挨个向前把每个面积都算一下
                if (i >= heights.length) {
                    while (posStack.peek() != -1) {
                        maxArea = getMaxArea(posStack, maxArea, i, heights[posStack.peek()]);
                    }
                }
                // 未到头时,当前值比栈顶小的,则向前计算面积,直到比栈顶大,压栈
                else {
                    while (heights[i] < (posStack.peek() == -1 ? -1 : heights[posStack.peek()])) {
                        maxArea = getMaxArea(posStack, maxArea, i, (posStack.peek() == -1 ? -1 : heights[posStack.peek()]));
                    }
                    posStack.push(i);
                }
            }
        }
        return maxArea;
    }

    private int getMaxArea(Stack<Integer> posStack, int maxArea, int i, int height) {
        posStack.pop();
        int area = height * (i - posStack.peek() - 1);
        return area > maxArea ? area : maxArea;
    }

}

三、单调栈整体思路

单调栈主要运用在给你一个数组序列,在遍历数组时,需要向前查看元素的这种情况,此时将前面的元素入栈,形成单调栈。具体再结合题目的用意,加以利用。

整体思路还是在于自己看如何利用单调栈,有一定的难度。

其它单调栈题解:

工藤新木:柱状图中最大的矩形(单调栈)

工藤新木:每日温度(单调栈)

工藤新木:下一个更大元素 II(单调栈)

工藤新木:最大矩形(单调栈)

工藤新木:接雨水(单调栈)

工藤新木:股票价格跨度(单调栈)

工藤新木:最大宽度坡(单调栈)

如有错误,请更正指出,谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值