LeetCode No.84 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 heights = [2,1,5,6,2,3],
return 10.
题目分析
这道题大意是将一个数组看作是直方图。求这个直方图内的最大矩形面积。
题干实在是简单。但是也实在开始没想到什么好方法。 索性先暴力做试试。
方法一 暴力穷举求解
这个方法很朴素。 就是穷举起点终点。然后算面积。 最后取最大值。就完了。
很明显的,一个
O(n2)
的方法。但是! 注意不要写成了
O(n3)
原因在于, 枚举起点终点的同时,需要记录下这个区间内的最小值。 不然计算高度的时候还得循环一遍。
代码如下:
好的,交上去果然超时了。我就知道一道Hard的题不可能这么简单。
但是这超时数据就很有意思了,
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1...]
emmm…..这种数据很容易就让人想到一种改进方法。
方法二 暴力求解改进版
唔。。。之所以这样叫, 是因为复杂度上并没有得到改进。还是
O(n2)
.
回到这个问题, 其实有一个明显的事实。我们刚才暴力求解其实做了许多无用运算。这是因为, 对于一个区间[i,j]
,若其矩形面积最大, 必然有nums[i - 1] < nums[i] && nums[j + 1] < nums[j]
.利用反证可以轻松证得这个结论。
利用这个性质,可以轻松写出2个条件来约束查找的范围。
还有一个,就是当相邻多个相等时, 我们是可以把这些点合并起来的。因为他们一定同时被选或者同时不被选。
嗯, 这样写完提交。 发现可以过了。 不过复杂度还是
O(n2)
. 代码如下:
方法三 利用stack解
上面那种显然还是比较暴力。 这种方法就是
O(n)
复杂度了。
怎么来描述这种方法呢?大致过程如下:
1. 首先将数组元素依次入栈。
2. 每次元素入栈时, 将入栈元素与栈顶元素相比。如果栈顶元素值更小,那么元素直接入栈。更大的话,弹出栈顶元素,并更新最大值。
这个方法其实感觉挺容易的。。。一开始自己却没有想到。囧了。。
代码:
class Solution {
public:
int largestRectangleArea(vector<int> &height) {
int ret = 0;
height.push_back(0);
vector<int> index;
for(int i = 0; i < height.size(); i++)
{
while(index.size() > 0 && height[index.back()] >= height[i])
{
int h = height[index.back()];
index.pop_back();
int sidx = index.size() > 0 ? index.back() : -1;
if(h * (i-sidx-1) > ret)
ret = h * (i-sidx-1);
}
index.push_back(i);
}
return ret;
}
};
其他细节
注意上面用栈的那个方法。 头尾要加上0, 不然会有问题。加上0才能保证搜索对解集是闭合的。
PS: 国庆有点小偷懒。。写的不多。 之后慢慢补回来吧:)