84.柱状图中最大的矩形

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

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        //法一:枚举宽,超时
        if(0){
            int n=heights.size();

            int area=0;
            for(int left=0;left<n;++left){
                int minH=INT_MAX;
                for(int right=left;right<n;++right){
                    minH=min(minH,heights[right]);
                    area=max(area,(right-left+1)*minH);
                }
            }
            return area;
        }else if(0){
        //法二:枚举高,超时
        //固定矩形的高度h,随后从这个柱子开始向两侧延伸,只到遇到高度小于h的柱子,就确定矩形的左右边界
            int n=heights.size();
            int area=0;

            for(int mid=0;mid<n;++mid){
                int h=heights[mid];
                int left=mid,right=mid;
                while(left-1>=0&&heights[left-1]>=h){
                    --left;
                }
                while(right+1<n&&heights[right+1]>=h){
                    ++right;
                }
                area=max(area,(right-left+1)*h);
            }
            return area;
        }else if(0){
            //法三:单调栈,是对枚举高的优化
            //求每一根柱子左侧且最近的小于其高度的柱子及右侧且最近的小于其高度的柱子,左右边界
            //若0位置大于1位置,则0可不能是2位置的左侧且最近的小于其高度的柱子,明显1位置更符合
            //单调栈栈中大于i位置的元素可以出栈
            int n=heights.size();
            vector<int> left(n),right(n);
            stack<int> ls,rs;

            for(int i=0;i<n;i++){
                while(!ls.empty()&&heights[ls.top()]>=heights[i]){
                    ls.pop();
                }
                left[i]=ls.empty()?-1:ls.top();
                ls.push(i);
            }

            for(int i=n-1;i>=0;--i){
                while(!rs.empty()&&heights[rs.top()]>=heights[i]){
                    rs.pop();
                }
                right[i]=rs.empty()?n:rs.top();
                rs.push(i);
            }

            int ans=0;
            for(int i=0;i<n;++i){
                ans=max(ans,(right[i]-left[i]-1)*heights[i]);
            }
            return ans;
        }else if(1){
            //法四:单调栈+常数优化
            int n=heights.size();
            //left记录i位置左侧最近的小于其高度的柱子下标
            //right记录i位置右侧最近的小于其高度的柱子的下标
            //单调栈中记录小于i位置柱子高度的位置下标,若高度大于等于则出栈,栈顶位置为左侧最近的小于i位置的柱子下标
            //左、右边界中的柱子均满足大于i位置的柱子高度,计算面积时以i位置柱子高度计算
            vector<int> left(n),right(n,n);
            stack<int> mono_stack;
            for(int i=0;i<n;i++){
                while(!mono_stack.empty()&&heights[mono_stack.top()]>=heights[i]){
                    right[mono_stack.top()]=i;
                    mono_stack.pop();
                }
                left[i]=mono_stack.empty()?-1:mono_stack.top();
                mono_stack.push(i);
            }
            int ans=0;
            for(int i=0;i<n;++i){
                ans=max(ans,(right[i]-left[i]-1)*heights[i]);
            }
            return ans;
        }
    }
}; 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值