力扣LCR 039. 柱状图中最大的矩形

100 阅读2分钟

力扣LCR 039. 柱状图中最大的矩形(单调栈)

思路
用到了单调栈。由于最大矩形它的高一定是height数组中的其中一个值,那么我们就可以遍历数组height的值再乘上它的宽的最大值WidthMax(宽的最大值后面会讲),然后取最大值就是答案,也就是ans=max(ans,WidthMax*height[x])。
那么如何求高为height[x]的宽的最大值WidthMax呢?
解题过程

如图,以黄色块为高所能撑起的最大范围即为红色部分,(数组heigh中的每个值都有可能是黄色块,所以后面要遍历一下)那么问题就转变为:
1.求从x开始的左边找第一个高度小于heigh[x]的长方形的下标l
2.同理,求从x的右边第一个小于heigh[x]的长方形的下标r
3.矩形的宽的最大值为WidhMax = r -l -1

那么问题又转变为如何求上面的l和r?
对于求r,此问题不就是已知数组的下标,求该下标开始从右边开始找第一个更小值吗?此时就可以用单调栈的思想来预处理每个点的右边界的值了,该过程与力扣中leetcode.cn/problems/ne…
那么l也同理,从左边开始找第一个更小值的下标
那么r[x]和l[x]就求出来了,
最后遍历每个小长方形,求(height[x]*(r[x]-l[x]-1))的最大值就是答案了

时间复杂度: 𝑂(𝑛)
空间复杂度: 𝑂(𝑛)

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //选定一个下标,从这个下标两边分别找第一个比它矮的下标(理解为找左边的第一个更小数,右边的第一个更小数),然后r-l-1个这样的矩形的和即为答案的可能之一
        const int N = 1e5+50;
        int l[N], r[N], s[N],top = -1;
        //预处理每个点的两边第一次碰到更矮的下标
        for(int i = 0; i < heights.size(); i++){
            int num = heights[i];
            while(top>=0&&heights[s[top]]>=num){
                top--;
            }
            if(top>=0)
                l[i] = s[top];
            else l[i] = -1;
            s[++top]=i;
        }
        top = -1;
        for(int i = heights.size()-1; i >= 0; i--){
            int num = heights[i];
            while(top>=0 && heights[s[top]] >= num)
                top--;
            if(top>=0) r[i] = s[top];
            else r[i] = heights.size();
            s[++top] = i;
        }
        int ans = 0;
        for(int i = 0; i < heights.size(); i++){
            ans = max(ans,(r[i]-l[i]-1)*heights[i]);
        }
        return ans;
    }
};