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.
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]
.
The largest rectangle is shown in the shaded area, which has area = 10
unit.
Example:
Input: [2,1,5,6,2,3]
Output: 10
方法一:计算以每条边为最短边的最大矩形
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int result = 0, len = heights.size();
for(int i = 0; i < len; i++){
int u = i, v = i;
while(u >= 0 && heights[u] >= heights[i]) u--;
u++;
while(v < len && heights[v] >= heights[i]) v++;
v--;
result = max(result,(v-u+1)*heights[i]);
}
return result;
}
};
方法二:递增栈
先把题中用递增栈的方法的实现步骤捋一捋,再来看为什么这么做可以
样例为2 1 5 6 2 3
i=0:栈为0
i=1:栈输出0,result更新,输入1
i=2:栈为1 2
i=3:栈为1 2 3
i=4:栈依次输出3 2,并动态更新result,输入4
i=5:栈为1 4 5
栈依次输出5 4 1,并动态更新result
Tips:更新result是指比较原有result,与i的左边第一条的边作为矩形右边的边,栈顶的右边的第一条边作为矩形左边,而围城的矩形的面积(有点拗口,理解一下),当然要是此时栈为空,左边的边的序号就以0算。
现在我们来考虑一下为什么递增栈实现这题的原理:
首先如果heights数组递增,怎么计算最大矩形?应该不至于往方法一的那种暴力想吧,从最后开始遍历,依次计算以该边作为最短边所得到的矩形面积,只要O(n)的复杂度。换言之,如果heights的单调递增的,计算最大面积就很方便,所以接下来我们的目标就是讲问题转化为递增数列求最大矩形面积。
其次再来看看递增栈,递增栈根据是否递增,将原数组分为 2// 1 5 6// 2 3三个部分,每次遇到一个不满足递增的数,我们进行分段,同时将上一个段中所有比该数大的边构成的部分递增序列进行处理,计算这个部分序列所能构成的最大的矩形面积,然后直接将这个部分序列放到一边,想一想为什么可以这么做。如果我们最终结果要用到这个递增序列构成矩形,就只有两种情况,一是只用到递增序列,这种我们已经运算过了,第二种会设计到旁边的边,重点来了,只要设计到两边的边,我们最后矩形的高度一定是小于该递增序列中任何一个,最后矩形在运算时,我们只会设计递增序列的长度,但是长度的话,想一想,我们既然栈存放的是数组的序号,长度其实也是隐含了的。既然如此,我们第一遍处理时直接去掉这些部分递增栈,我们最后留下的一定是一个递增序列,同理进行处理即可。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int result = 0, len = heights.size();
stack<int>s;
for(int i = 0; i < len; i++){
if(s.empty() || heights[s.top()] <= heights[i])
s.push(i);
else{
while(!s.empty() && heights[s.top()] >= heights[i]){
int temp = s.top(),temph;
s.pop();
temph = s.empty() ? i : i-s.top()-1;
result = max(result, heights[temp] * temph);
}
s.push(i);
}
}
while(!s.empty()){
int temp = s.top(),temph;
s.pop();
temph = s.empty() ? len : len-s.top()-1;
result = max(result,heights[temp]*temph);
}
return result;
}
};