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 height = [2,1,5,6,2,3]
,
return 10
.
题目分析:
题意非常清楚,就是寻找直方图中的最大矩形面积。
看似非常简单,最先想到的方法就是穷举法,从头开始往后寻找,或者通过剪枝确定可能的右边界向前寻找,时间复杂度O(n2)。这个算法显然在数据很多或者递增递减的图中会挂掉。
根据助教的提示,下面考虑使用栈:
通过观察可以发现,矩形一定在夹在两个较小的矩形的中间,而且一定有矩形右边的元素高度小于矩形最左端的元素的高度,例如上图中高度2小于矩形最左端高度5。
也就是说计算的矩形一定是一个类似”波峰“的形状。
从而我们可以从头遍历集合,当遇到大于当前栈顶元素高度的元素时,进栈;否则,依次出栈,直到栈顶小于等于当前高度,计算面积。并将当前元素压入栈内。
此解法的核心思想为:一次性计算连续递增的区间的最大面积,并且考虑完成这个区间之后,考虑其前、后区间的时候,不会受到任何影响。也就是这个连续递增区间的最小高度大于等于其前、后区间。
代码如下:
class Solution { public: int largestRectangleArea(vector<int>& height) { stack<int> index_height; height.push_back(0); //加入立柱0,作为结尾判断 int area = 0; for (int i = 0; i < height.size(); i++) { if (index_height.empty() || (!index_height.empty() && height[i] >= height[index_height.top()])) //如果比栈顶的高度大,则进栈,构建单调栈 index_height.push(i); else { //比栈顶的高度小,开始依次出栈,并记录下标 while (!index_height.empty() && height[index_height.top()] > height[i]) { int index = index_height.top(); index_height.pop(); int width = index_height.empty() ? i : (i - index_height.top() - 1); //计算弹出的面积 area = max(area, height[index] * width); } index_height.push(i); // 将当前进栈 } } return area; } };
提交到OJ,可以AC通过。但发现普遍C语言的程序速度更快,想了好久,以为有什么更好地方法。后来想到,C语言里没有用栈,直接顺序存储的数组访问起来更加快。 0.0
此博客中的内容均为原创或来自网络,不用做任何商业用途。欢迎与我交流学习,我的邮箱是lsa0924@163.com