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.youkuaiyun.com/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;
}
};