84.柱形图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

在这里插入图片描述

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

在这里插入图片描述

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

示例:

输入: [2,1,5,6,2,3]
输出: 10

来源:力扣(LeetCode)


首先肯定暴力啊,思想:矩形有长宽啊,暴力枚举。。。wa在了最后一个样例(样例个数超1W)

class Solution {
public:
   int largestRectangleArea(vector<int>& heights) {
        int ans=0;
         int wid=0;
         int tep=0;
        for(auto hei:heights){//矩形长
            for(auto cn:heights){
                if(hei<=cn){
                    wid++;//矩形宽
                    tep=hei*wid;
                }else{
                    ans=max(ans,tep);
                    tep=0;
                    wid=0;
                }   
            }
			ans=max(ans,tep);
			tep=0;
            wid=0;
        }
        return  ans;
    }
};

分治法,
1.确定了最矮柱子以后,矩形的宽尽可能往两边延伸。
2.在最矮柱子左边的最大面积矩形(子问题)。
3.在最矮柱子右边的最大面积矩形(子问题)。

class Solution {
public:
  int calculate(vector<int>&heights,int start,int end){
        if(start>end) return 0;
        int mini=start;
        for(int i=start;i<=end;i++){
            if(heights[mini]>heights[i]){ 
                mini=i;
            }
        }
        return max(heights[mini]*(end-start+1),max(calculate(heights,start,mini-1),calculate(heights,mini+1,end)));
    }
    int largestRectangleArea(vector<int>& heights) {
        return calculate(heights,0,heights.size()-1);
    }
};

当时还用minH=0x3f3f3f3f,没想到有个样例是int的最大范围,这个说明一定要谨慎。平均O(nlogn),最坏O(n^2).


看了一下大佬的思想。
以第i根柱子为最矮柱子所能延伸的最大面积。具体就是找出第i根柱子左边第一个小于heights【i】的下标left_i;右边也是,找出第一个小于heights【i】的下标right_i,则面积是heights【i】*(right_i - left_i -1)
剩下的就是如何高效的找出这两个数组了。
1.如果heights【i-1】>=heights【i】,那么问题转化为找出第i-1柱子左边的柱子。

//遍历左边
for(i from 0 to heights.size(){
	int tmp=i-1;
	while(heights[i-1]>=heights[i]) tmp=left_i[tmp];
	left_i[i]=tmp;
)
//在添加一些边界即可。

总体代码

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        if(heights.empty()) return 0;//力扣上数组长度可能为0
        int size=heights.size();
        int  left_i[size+1];
        int right_i[size+1];
        left_i[0]=-1;
        right_i[size-1]=size;
        for(int i=1;i<size;i++){
            int tmp=i-1;
            while(tmp>=0&&heights[tmp]>=heights[i]) tmp=left_i[tmp];
            left_i[i]=tmp;
        }
        for(int i=size-2;i>=0;i--){
            int tmp=i+1;
            while(tmp<size&&heights[tmp]>=heights[i]) tmp=right_i[tmp];
            right_i[i]=tmp;
        }
        int ans=0;
        for(int i=0;i<size;i++){
            ans=max(ans,heights[i]*(right_i[i]-left_i[i]-1));
        }
        return ans;
    }
};
  1. 单调栈
    栈里面的元素是递增的。保存的是矩形的下标。

当柱子的高度递增时,入栈柱子的下标。
当出现柱子(i)的高度小于栈顶时(右边第一个高度小于他的矩形),可以套公式计算了。
right_i=i, left_i =弹出栈之后的栈顶(栈里面是递增的,弹出栈之后,找到了左边第一个小于他的矩形),高度=heights[ 当前栈顶]。
遍历完了之后,栈里面可能还有元素。这时要注意 right_i 始终等于= heights.size()了。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        stack<int>st;
        st.push(-1);
        int size=heights.size();
        int ans=0;
        for(int i=0;i<size;i++){
            while(st.top()!=-1&&heights[i]<heights[st.top()]){
                int top=st.top();
                st.pop();
                ans=max(ans,heights[top]*(i-1-st.top()));
            }
            st.push(i);
        }
        while(st.top()!=-1){
            int top=st.top();
            st.pop();
            ans=max(ans,heights[top]*(size-1-st.top()));
        }
        return ans;
    }
};

不得不说这个-1和size真是太妙了!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值