【Leetcode单调栈】单调栈深入总结

1.目录

在这里插入图片描述

2.单调栈作用:

以o(n)的时间复杂度,找到数组内所有元素左边(右边)第一个比自己大(小)的元素(或下标)

1.单调栈已经做了五道题了,别的都不多说,单调栈就一个作用,遇到需要这个作用的都想到单调栈,以o(n)的时间复杂度,找到数组内所有元素左边(右边)第一个比自己大(小)的元素(或下标)
2.每日温度不说了就是找右边第一个比自己大的元素
3.下一个更大元素I 下一个更大元素Ⅱ 这还用说吗,直接就是找右边第一个比自己大的元素+一点点绕弯子
3.接雨水,其实是找左右最大的元素,但是由于单调栈只会找第一个大的元素,所以我们要想从问题层面转化问题,那就是按行求雨水,然后就可以使用单调栈的功能了。
4.柱状图的最大矩形,和接雨水很像,接雨水时一个凹然后求值,这道题是一个凸求值,几乎是一样的!
5.所以总结来总结去,单调栈就一个功能,以o(n)的时间复杂度,找到数组内所有元素左边(右边)第一个比自己大(小)的元素(或下标),如果题目不能直接使用这个功能完成,就像接雨水和柱状图,那就从问题层面想办法通过转化使用上这个单调栈的功能!


2.单调栈代码示例:

简介版:

class Solution2 {
public:
    int trap(vector<int>& height) {
        //存着下标,计算的时候用下标对应的柱子高度
        stack<int> stack;
        int sum=0;
        //构建单调栈
        stack.push(0);
        for(int i=1;i<height.size();i++){
            while(stack.empty()== false&&height[stack.top()]<height[i]){
                int mid=stack.top();
                stack.pop();
                if(stack.empty()== false){
                    int left=height[stack.top()];
                    int right=height[i];
                    int h=min(left,right)-height[mid];
                    int width=i-stack.top()-1;
                    sum+=h*width;
                }
            }
            stack.push(i);
        }
        return sum;
    }
};

逻辑清晰版:

class Solution1 {
public:
    int trap(vector<int>& height) {
        //存着下标,计算的时候用下标对应的柱子高度
        stack<int> stack;
        int sum=0;
        //构建单调栈
        stack.push(0);
        for(int i=1;i<height.size();i++){
            //1.
            if(height[stack.top()]>height[i]){
                stack.push(i);
                continue;
            }
            //2.
            if(height[stack.top()]==height[i]){
                //其实这一句可以不加,效果是一样的,但处理相同的情况的思路却变了。
                stack.pop();
                stack.push(i);
                continue;
            }
            //3.
            if(height[stack.top()]<height[i]){
                while(stack.empty()== false&&height[stack.top()]<height[i]){
                    int mid=stack.top();
                    stack.pop();
                    if(stack.empty()== false){
                        int left=height[stack.top()];
                        int right=height[i];
                        int h=min(left,right)-height[mid];
                        int width=i-stack.top()-1;
                        sum+=h*width;
                    }
                }
                stack.push(i);
            }
        }
        return sum;
    }
};

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值