Leetcode单调栈问题

单调栈的定义

  • 单调递增栈:单调递增栈就是从栈底到栈顶数据是从大到小
  • 单调递减栈:单调递减栈就是从栈底到栈顶数据是从小到大

42、接雨水
在这里插入图片描述
解析:
对于每一个高度的柱子来说如果想要以它为底盛水,那么它的左右两根柱子都必须比他要高,所以定义一个单调增栈,先保证栈中的元素左边都比右边要大,这时候只要再添加的元素大于栈顶的元素就满足了接水的条件了,这时候就可以计算以栈顶元素高度为底的能接多少水,算出后将其弹出,再次比较栈顶元素是否还能为底来接水,可以的话继续计算,知道无法再节水为止。左边界条件就是栈里必须有一个元素才可以接水,所以当栈为空时也跳出循环。

class Solution {
    public int trap(int[] height) {
        int n = height.length;
        if(n == 0) return 0;
        int res = 0;
        Stack<Integer> stack = new Stack<>();

        for(int i = 0; i < n; i++){
            while(!stack.isEmpty() && height[i] > height[stack.peek()]){
                int cur = height[stack.pop()];
                if(stack.isEmpty()) break;
                int width = i - stack.peek() - 1;
                int h = Math.min(height[i], height[stack.peek()]);
                res += width * (h - cur);
            }
            stack.push(i);
        }
        return res;

    }
}

84、柱状图中的最大矩形
在这里插入图片描述
解析:确定以一根柱子的高度为高的矩形的体积,宽度要想两边搜索知道遇见高度小于当前高度的矩形停止,即要确定矩形的大小那么他两边的柱子的高度要小于它自己的高度,因此设计一个栈,这个占中的元素栈顶的一定要大于栈底的元素,此时一旦遇见小的元素,就可以计算这个矩形为高的矩形的宽度了,就可以计算出这一块的面积。
以此比较就可以得出最大的面积。

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length;
        if(n == 0) return 0;
        int res = 0;
        int[] newheights = new int[n + 2];
        newheights[0] = newheights[n + 1] = 0;
        for(int i = 1; i < n + 1; i++){
            newheights[i] = heights[i - 1];
        }
        Stack<Integer> stack = new Stack<>();
        for(int i = 0; i < n + 2; i++){
            while(!stack.isEmpty() && newheights[i] < newheights[stack.peek()]){
                int cur = stack.pop();
                int curheights = newheights[cur];
                int leftIndex = stack.peek();
                int rightIndex = i;
                int curWidth = rightIndex - leftIndex - 1;
                res = Math.max(res, curWidth * curheights);
            }
            stack.push(i);
        }
        return res;        
    }
}

总结:上边两道题目都是分别计算以每一个矩形的高度为底或者为顶,能接的水或者围成的面积,需要确定的就是宽度,根据具体的条件来判断是使用单调增还是单调减栈,这样就可以判断宽度了。

739、每日温度

在这里插入图片描述
解析:如果采用暴力算法,对于每一天都向后遍历找高温的话复杂度是n^2,所以想到使用单调栈来解决这样只要遍历一遍数组就可以得出结果复杂度只是n。找高温,那么就使用单调增栈。一旦遇到比当前元素打的就弹出栈计算天数,最后留在栈内的元素就是没有比他高的温度了,直接就是0.

class Solution {
    public int[] dailyTemperatures(int[] T) {
        int n = T.length;
        if(n == 0) return new int[]{};
        Stack<Integer> stack = new Stack<>();
        int[] res = new int[n];
        for(int i = 0; i < n; i++){
            while(!stack.isEmpty() && T[i] > T[stack.peek()]){
                int cur = stack.pop();
                res[cur] = i - cur;
            }
            stack.push(i);
        }
        return res;

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值