(Nice!!!)LeetCode 84. 柱状图中最大的矩形(数组、单调栈)

84. 柱状图中最大的矩形

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

思路:方法一:我们可以两层循环枚举左右边界,通过一直更新最小高度值,找到最优值,但时间复杂度为0(10^10).
方法二:一层循环枚举每个点,再加上一个循环寻找左右边界,更新最优值,时间复杂度为0(10^2)
方法三:我们根据方法二,来进行优化。我们可以维持一个单调递增的栈,然后每次找到比他小的值的下标,时间复杂度为0(10^5),具体细节看代码。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> l,r;//左右两边的递增栈
        vector<int> v1(heights.size()),v2(heights.size());//保存每个下标i对应的左右两个边界(这两个边界对应的高度都是首次低于heights[i])
        for(int i=0;i<heights.size();i++){//先从左到右遍历,找到左边最近的下标
            while(!l.empty()&&heights[l.top()]>=heights[i]){//栈不为空且栈顶元素对应的高度>=当前的高度
                l.pop();//进行出栈操作
            }
            if(!l.empty())v1[i]=l.top();//如果栈不为空,说明目前栈顶元素对应的高度是首个低于当前高度的。
            else v1[i]=-1;//栈顶为空,说明没有比他还低的高度,那么我们默认为-1,便于后续计算面积。
            l.push(i);//插入当前高度,说明每个数都只会进栈一次
        }

        for(int i=heights.size()-1;i>=0;i--){//从右到左遍历,找到右边最近的下标
            while(!r.empty()&&heights[r.top()]>=heights[i]){//栈不为空且栈顶元素对应的高度>=当前的高度
                r.pop();//进行出栈操作
            }
            if(!r.empty()) v2[i]=r.top();//如果栈不为空,说明目前栈顶元素对应的高度是首个低于当前高度的。
            else v2[i]=heights.size();//栈顶为空,说明没有比他还低的高度,那么我们默认为heights.size(),便于后续计算面积。
            r.push(i);//插入当前高度,说明每个数都只会进栈一次

        }
        int maxx=0;
        for(int i=0;i<heights.size();i++){//遍历每个点,找到最优值
            maxx=max(maxx,(v2[i]-v1[i]-1)*heights[i]);//-1是因为保存的下标都是不满足要求的
            printf("%d-%d\n",v1[i],v2[i]);
        }
        return maxx;
    }
};

思路:方法四,是对方法三时间和空间的一个优化。我们会发现每次出栈操作都是栈顶的高度大于当前的高度,那么对于栈顶元素来说,右边第一个比他低的下标,就是当前的i。那么我们在第一次循环当中就可以保存到左右两边的边界。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int> l;
        vector<int> v1(heights.size()),v2(heights.size());
        for(int i=0;i<heights.size();i++){
            while(!l.empty()&&heights[l.top()]>=heights[i]){
                v2[l.top()]=i;//对于栈顶元素来说,右边第一个比他低的下标,就是当前的i
                l.pop();//一定要明确,每个点都会进栈一次
            }
            if(!l.empty())v1[i]=l.top();
            else v1[i]=-1;
            l.push(i);
        }
        while(!l.empty()){//如果栈不为空,说明,右边的高度都是比他大,符合要求的。
            v2[l.top()]=heights.size();
            l.pop();
        }
        int maxx=0;
        for(int i=0;i<heights.size();i++){
            maxx=max(maxx,(v2[i]-v1[i]-1)*heights[i]);
            printf("%d-%d\n",v1[i],v2[i]);
        }
        return maxx;
    }
};
  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值