[LeetCode] Largest Rectangle in Histogram

Largest Rectangle in Histogram Given n non-negative integers
representing the histogram’s bar height where the width of each bar is
1, find the area of largest rectangle in the histogram.
这里写图片描述
这里写图片描述

For example,
Given height = [2,1,5,6,2,3], return 10.

当我们判断包含height[k], 我们要找到相邻的不比height[k]小的最大范围i,j
那么这个长方形的面积为height[k]*[j-i+1]

bf的方法是对于每一个窗口,寻找其中最低的高度,那么这个窗口对应的长方形面积等于窗口长度乘以最低高度。复杂度为O(n^2*n)

第二种思路是从左往右移动一个bar,对于每一个bar找它左右不比它小的下标。O(n^2),但是会TLE。

class Solution {
public:
    int largestRectangleArea(vector<int>& height) {
        int front,rear,win=0,N;
        int max_area = 0;
        int win_height;
        N = height.size();
        while(win<N){
            front = rear= win;
            win_height = height[win];
            while(front>=0&&height[front]>=win_height)  {--front;}
            while(rear<N&&height[rear]<=win_height) {++rear;}
            max_area = max(max_area,(rear-front+1)*win_height);
            ++win;
        }
        return max_area;

    }
};

另外一种解法是最优解法,维护一个栈,这个栈内存的是元素的下标。当前的下标为bar,如果栈为空或是栈的top元素比小,那么push(bar);否则移动指针,找到bar前面的不比bar小的最远的。

会发现,stack中保存的都是递增的元素索引,每一次top的元素满足>=bar时就更新下max_area,下面引用下http://blog.csdn.net/doc_sgl/article/details/11805519 图例来说明下

1、首先,如果栈是空的,那么索引i入栈。那么第一个i=0就进去吧。注意栈内保存的是索引,不是高度。然后i++。入栈后i变成i=1;
这里写图片描述

2、然后继续,当i=1的时候,发现h[i]小于了栈内的元素,于是出栈。(由此可以想到,哦,看来stack里面只存放height单调递增的索引)

这时候stack为空,所以面积的计算是h[t] * i。t是刚刚弹出的stack顶元素。也就是蓝色部分的面积。
这里写图片描述

3、继续。这时候stack为空了,继续入栈,i=1。注意到只要是连续递增的序列,我们都要keep pushing,直到我们遇到了i=4,h[i]=2小于了栈顶的元素。
这里写图片描述

4、这时候开始计算矩形面积。首先弹出栈顶元素,t=3。即下图绿色部分。

这里写图片描述

5、接下来注意到栈顶的(索引指向的)元素还是大于当前i指向的元素,于是出栈,并继续计算面积,粉色部分。
这里写图片描述

6、最后,栈顶的(索引指向的)元素小于了当前i指向的元素,循环继续,入栈并推动i前进。直到我们再次遇到下降的元素,也就是我们最后人为添加的dummy元素0.
这里写图片描述
注意我们在计算面积的时候已经更新过了maxArea。

class Solution {
public:
    int Max(int a, int b){return a > b ? a : b;}
    int largestRectangleArea(vector<int> &height) {
        height.push_back(0);
        stack<int> stk;
        int i = 0;
        int maxArea = 0;
        while(i < height.size()){
            if(stk.empty() || height[stk.top()] <= height[i]){
                stk.push(i++);
            }else {
                int t = stk.top();
                stk.pop();
                maxArea = Max(maxArea, height[t] * (stk.empty() ? i : i - stk.top() - 1));
            }
        }
        return maxArea;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值