84. Largest Rectangle in Histogram

#84. Largest Rectangle in Histogram(求矩形最大面积)

题目来源:

https://leetcode.com/problems/largest-rectangle-in-histogram/description/

题意分析:

给一个正整数列表,每个数字x在直方图上表示宽度为1的矩形的高度,求直方图中的最大矩形。


 

题目思路:

最大矩形的高是由组成矩形的小矩形的最小高度决定的,对于列表[x1,x2,x3,...],每个x都有可能是最大矩形的最小高度,对于这个x,高度确定了,只要求出最大宽度就可以求解。所以问题可以转化为求以x为轴,左右边第一个比x小的值的下标。然后最大矩形就是所有x求出的矩形的最大项。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int left,right;
        int res=0;
        for (int i=0; i<heights.size(); i++){
            left=i;
            right=i;
            while(left>=0&&heights[left]>=heights[i])
                left--;
            while(right<heights.size()&&heights[right]>=heights[i])
                right++;
            res=res>(right-left+1)*heights[i]?res:(right-left-1)*heights[i];
        }
        return res;
        
    }
};

上述解法的时间复杂度是O(n^2),提交后超时了,那么只能想O(n)或者O(nlogn)的算法了。我们会发现大部分的时间都用在了求left跟right上,我们可以用一个栈s来优化这一过程。

求right的思路如下,s保存的是没有求到right值的值的列表下标,开始为空。从左到右遍历列表,如果s空或者heights[s.top()]<=heights[i],即当前的高度不小于s栈顶高度的话,把当前高度的下标推进s。如果heights[s.top()]>heights[i],当前的高度比s栈顶高度要小,那么i就是前面那些比heights[i]大且没求到right值的值的right值,弹出s中所有比heights[i]大的值并把right值设为i,然后再把i推进s。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        // heights.push_back(0);
        vector<int> left(heights.size(),-1);
        vector<int> right(heights.size(),heights.size());
        stack<int> s;
        // s.push(0);
        for (int i=0; i<heights.size(); i++){
            cout<<i<<endl;
            while (s.size()>0&&heights[i]<heights[s.top()]){
                right[s.top()]=i;
                s.pop();
            }
            s.push(i);
        }
        s=stack<int>();
        //s.push(0);
        for (int i=heights.size()-1; i>=0; i--){
            while (s.size()>0&&heights[i]<heights[s.top()]){
                left[s.top()]=i;
                s.pop();
            }
            s.push(i);
        }
        // for(int i=0; i<heights.size(); i++)
        //     cout<<left[i]<<" "<<right[i]<<endl;
        int res=0;
        for(int i=0; i<heights.size(); i++){
            res=res>(right[i]-left[i]-1)*heights[i]?res:(right[i]-left[i]-1)*heights[i];
        }
        return res;
        
    }
};

这一解法时间复杂度为O(n),因为对于每个i,right[i],left[i]只计算了一次。提交后A了,但时间长到看不到百分号。

我们观察栈s,如果把它里面的坐标i映射到heights[i],那么它是有序的,栈底到栈顶heights由小到大,而且在不断push,pop的过程中依然能保持,那么我们在求到栈顶元素的right值时,如果把栈顶元素pop出来,剩下的栈顶元素就是就是左边第一个heights比开始栈顶元素的heights小的下标,那么我们在求right的时候就可以求出left已经矩形面积了。

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



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值