难度:hard
描述:
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.
For example,
Given heights = [2,1,5,6,2,3]
,
return 10
.
思路:
真的难,如果要暴力做的话O(N^2)复杂度,过不了。
上网一搜解答,发现了这个用栈来解决的算法,代码不长,但是看着很迷。
下面就以题目给的例子来看看这个算法怎么工作:
基本思路是维护一个递增的栈,就是说栈内的长条的长度都是递增的,绝不存在上层元素小于下层的情况。
但是这个栈为了方便计算面积,记录的是长条在题目给出的heights数组的索引而不是长度。
有记录最大面积的变量max ,初始化为0
所以我们就开始入栈:指针p在heights数组上从0开始递增
p = 0, 遇到2,入栈
p = 1,遇到1,小于栈顶元素,不能放进去了,要出栈:
首先记住栈顶的长度2,他是height,然后pop,这时栈为空。宽度直接为p,这时为什么呢?
我们知道,某个长条和另外长条一起计算面积且以它的长度为高,那么另外长条的长度一定不能小于它的长度,不然就不能以它的长度来作为合并出来的矩形的高了。
而我们维护的是个递增的栈,那么此时空栈意味着,该长条的左边不存在比他短的长条!所以可以直接用p来作为宽度
如果不为空呢?那么宽度为p-(stack.top+1),意思是矩形宽度到stack.top的前面,stack.top过短,挡住了矩形的延展。
然后求面积,如果大于max,就更新max。
最后整个栈都空了,最大面积也求出了,这个算法时间复杂度O(n)
很巧妙,但是理解起来很费解。
代码:
#include<stack>
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
if (heights.size() == 0) return 0;
std::stack<int> s;
int max = 0;
int i = 0;
while(i < heights.size()){
if (s.empty() || heights[s.top()] <= heights[i]){
s.push(i);
i++;
} else {
int height = heights[s.top()];
s.pop();
int width = s.empty()?i:i-s.top()-1;
if (width*height > max) max = width*height;
}
}
while (!s.empty()) { // empty the stack
int height = heights[s.top()];
s.pop();
int width = s.empty()?i:i-s.top()-1;
if (width*height > max) max = width*height;
}
return max;
}
};