84. 柱状图中最大的矩形

在这里插入图片描述
在这里插入图片描述
暴力超时,明天就做单调栈

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //最大=最优解≈dp
        /*if(heights.size() == 0) return 0;
        int maxArea = INT_MIN;
        for(int i = 0;i<heights.size();++i){
            int left = i, right = i;
            while(left-1 >= 0 && heights[left-1] >= heights[i]) left--;
            while(right+1 <= heights.size()-1 && heights[right+1] >= heights[i]) right++;
            maxArea = max((right-left+1)*heights[i],maxArea);
        }
        return maxArea;*/

        //因为要找到左右两边第一个比自己小的,所以维护一个单调栈便可以在O(n)的时复下找到左右两边比自己小的,自身这个元素下面记录着左边第一个比自己小的元素,而遍历时可以得到右边第一个比自己小的元素,因为要求宽度,所以栈里记录的是下标
        stack<int> sta;
        //如果当前遍历到的柱子小于栈顶,就证明找到了
        //防止所有柱子都是单调递增的
        heights.push_back(0);
        int maxArea = 0;
        for(int i = 0; i < heights.size(); ++i){
            while(!sta.empty() && heights[sta.top()] > heights[i]){
                int top = sta.top();
                sta.pop();
                //以栈顶柱子为高,宽为右-左-1,但是左边有可能没有值,左边没有值证明它是从0一直到i的,所以宽度是i
                maxArea = max(maxArea, heights[top]*(sta.empty()?i:(i-sta.top()-1)));
            }
            sta.push(i);
        }
        return maxArea;
    }
};

细节满满的题,不仅要知道单调栈现在在做什么,更要考虑多种情况。比如数组本身单调递增,或者sta为空的情况。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //单调递增栈,因为我们要找的是当前柱子左右第一个小于自身的柱子
        //左边的柱子就是弹出栈顶后的新栈顶,右边的柱子就是新遍历到的这个柱子
        //其实单调栈的目的就是找出以每个栈顶往左右发散的宽度,发散到比自己小的就不能发散了
        //有可能是单调递增的数组,比如123这样的数组,那么就永远找不到右边比自己小的数字
        //所以我们要在最后加上一个0,不会影响结果
        stack<int> sta;
        heights.push_back(0);
        int res = 0;
        for(int i = 0; i < heights.size(); ++i){
            while(!sta.empty() && heights[sta.top()] > heights[i]){
                int top = sta.top();
                sta.pop();
                //左边要注意,有可能弹出后栈是空的了,代表从0开始到当前判断的栈顶,没有一个数字比自己小,就当作都比自己大好了,那么宽就是i-0
                res = max(res,heights[top]*(sta.empty()?i:(i-sta.top()-1)));
            }
            sta.push(i);
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值