单调栈的应用题

在这里插入图片描述

题:接雨水

在这里插入图片描述
本题单调栈的作用:1.便于获取top的左墙;2.便于寻找右墙
在这里插入图片描述

class Solution {
    public int trap(int[] height) {


        int len=height.length;
        int res=0;

        //利用双向队列实现“单调递减的栈”(栈内存放的是序号,栈顶元素最小)
        //因为需要维护单调栈,才会有出栈的操作
        Deque<Integer> stack=new LinkedList<>();
        
        for(int i=0;i<len;i++){

            //当当前高度大于时,就不满足单调性了,所以不能直接加入
            //可能height[i]大于栈中的好几个元素,所以需要while循环
            while(!stack.isEmpty() && height[i]>height[stack.peek()]){
                //首先出栈(获取top下面的left左墙),栈中至少两个元素才有意义
                int top=stack.pop();
                
                //如果top没有左墙,也就没法保存雨水
                if(!stack.isEmpty()){
                    int left=stack.peek();//注意这里是peek(),可能这个left的高度小于height[i]
                    int broadLen=i-left-1;
                    int hLen=Math.min(height[i],height[left])-height[top];
                    res=res+broadLen*hLen;
                }
            }

            //满足单调性,序号直接加入栈中(height[i]小于等于栈顶元素才开始入栈)
            stack.push(i);
        }

        return res;

    }
}

题:每日温度
在这里插入图片描述
当前元素大于栈顶元素,说明当前元素是栈顶元素的后面的第一个更高温度的天,就可以求出栈顶元素的answer

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int len=temperatures.length;
        int[] answer=new int[len];

        //使用单调栈(递减栈来实现),如果小于等于栈顶的元素就直接入栈
        Deque<Integer> stack=new LinkedList<>();
        for(int i=0;i<len;i++){
            
            int curtemp=temperatures[i];

            //如果当前元素大于栈顶元素,那么这个栈顶元素的answer就可以求了
            //可能这个元素是栈中好几个元素的高温天
            while(!stack.isEmpty() && curtemp>temperatures[stack.peek()]){
                int left=stack.pop();
                answer[left]=i-left;
            }
            stack.push(i);
        }

        return answer;
        

    }
}

题:柱子图中的最大矩形(左右的两遍单调栈的情况)

在这里插入图片描述

class Solution {
    public int largestRectangleArea(int[] heights) {

        int len=heights.length;
        int res=0;

        int[] leftQ=new int[len];//寻找左边界(刚好左边第一个小于本位置高度的序号)
        int[] rightQ=new int[len];//寻找右边界(刚好右边第一个小于本位置高度的序号)

        //利用一个单调递增的栈,寻找左边界(刚好左边第一个小于本位置高度的序号)
        Deque<Integer> stack=new LinkedList<>();
        for(int i=0;i<len;i++){
            //寻找小于heights[i]的元素的序号
            while(!stack.isEmpty() && heights[i]<=heights[stack.peek()]){
                stack.pop();           
            }

            leftQ[i]=stack.isEmpty()?-1:stack.peek();//如果栈为空,说明它没有左边比它小的墙(哨兵:-1--是的,不满足的第一个序号)
            stack.push(i);
        }


        stack.clear();//清楚所有的元素(复通这个栈)


        //利用一个单调递增的栈,寻找右边界(刚好右边第一个小于本位置高度的序号)
        for(int i=len-1;i>=0;i--){
            //寻找小于heights[i]的元素的序号
            while(!stack.isEmpty() && heights[i]<=heights[stack.peek()]){
                stack.pop();           
            }

            rightQ[i]=stack.isEmpty()?len:stack.peek();//如果栈为空,说明它没有右边比它小的墙(哨兵:len--是的,不满足的第一个序号)
            stack.push(i);
        }


        for(int i=0;i<len;i++){
            res=Math.max(res,(rightQ[i]-leftQ[i]+1-2)*heights[i]);
        }

        return res;

  

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值