[leetcode]84.Largest Rectangle in Histogram ,O(n)解法剖析
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
.
题目描述:就是给你一组数组,每个位置上的数都代表一个宽度为1的矩形柱,求你能得到的面积最大的矩形柱的面积。这里要注意,如果是[2,1,2],输出的结果应该是3而不是2,是从3个矩形柱中截取高度为1的矩形拼接而成的。
没有什么题目是纯暴力不能解决的,当然考虑到时间复杂度和空间复杂度,这个还是有可能会崩的。
以下是一个O(n)的解法,并不是我的原创。
首先我们看一下下面的例子:
height的内容是 [5,6,7,8,3],特点是除了最后一个,前面全部保持递增,且最后一个立柱的高度小于前面所有立柱高度。
对于这种特点的柱状图,如果使用上面所说的“挨个使用每一个柱状图的高度作为矩形的高度,求面积”的方法,还需要用嵌套循环吗?
我们知道除了最后一个,从第一个到倒数第二个立柱的高度都在升高,那么如果挨个使用每一个柱的高度作为矩形的高度,那么依次能得到的矩形的宽度就可以直接算出来:使用5作为高度可以使用前四个立柱组成 4*5的矩形,高度6可以组成3*6的矩形... 因此只需要遍历一次,选出最大面积即可。
对于这种类型的柱状图,最大矩形面积的时间复杂度是O(n)。
我们将这种特点的柱状图称为“波峰图”。
下面介绍新的解法的步骤:
(1) 在height尾部添加一个0,也就是一个高度为0的立柱。作用是在最后也能凑成上面提的那种“波峰图”。
(2) 定义了一个stack,然后遍历时如果height[i] 大于stack.top(),进栈。反之,出栈直到栈顶元素小于height[i]。
由于出栈的这些元素高度都是递增的,我们可以求出这些立柱中所围成的最大矩形。更妙的是,由于这些被弹出的立柱处于“波峰”之上(比如弹出i 到 i+k,那么所有这些立柱的高度都高于 i-1和 i+k+1的高度),因此,如果我们使用之前所提的“左右延伸找立柱”的思路解,以这些立柱的高度作为整个矩形的高度时,左右延伸出的矩形所包含的立柱不会超出这段“波峰”,因为波峰外的立柱高度都比他们低。“波峰图”其实就是求解最大矩形的“孤岛”,它不会干扰到外部。
(3) 由于比height[i]大的元素都出完了,height[i]又比栈顶元素大了,因此再次进栈。如此往复,直到遍历到最后那个高度为0的柱,触发最后的弹出以及最后一次面积的计算,此后stack为空。
(4) 返回面积最大值。
栈中存的不是高度,而是height的索引,这样做的好处是不会影响宽度的计算,索引值相减 = 宽度。
int largestRectangleArea(vector<int> &h) {
stack<int> S;
h.push_back();
int sum = ;
for (int i = ; i < h.size(); i++) {
if (S.empty() || h[i] > h[S.top()]) S.push(i);
else {
int tmp = S.top();
S.pop();
sum = max(sum, h[tmp]*(S.empty()? i : i-S.top()-));
i--;
}
}
return sum;
}
此解法最大亮点就在于:
(1) stack里存的是index,计算面积时的宽度使用 index的差值,所以虽然stack 弹出了立柱,但是不影响宽度的计算,依然可以计算面积。
(2) 这种解法本质上是查看以每一个立柱为矩形高度,求出最大面积,但是它通过入栈出栈,把整个height变成一组组“波峰图”来解,这种高度布局下,最大面积的计算是O(n)的,然后将所有波峰图的最大面积取最大值。最后做到了以O(n)的时间复杂度覆盖了所有的立柱。
非常值得学习。
[leetcode]84.Largest Rectangle in Histogram ,O(n)解法剖析的更多相关文章
- LeetCode 84. Largest Rectangle in Histogram 单调栈应用
LeetCode 84. Largest Rectangle in Histogram 单调栈应用 leetcode+ 循环数组,求右边第一个大的数字 求一个数组中右边第一个比他大的数(单调栈 Lee ...
- 关于LeetCode的Largest Rectangle in Histogram的低级解法
在某篇博客见到的Largest Rectangle in Histogram的题目,感觉蛮好玩的,于是想呀想呀,怎么求解呢? 还是先把题目贴上来吧 题目写的很直观,就是找直方图的最大矩形面积,不知道是 ...
- [LeetCode] 84. Largest Rectangle in Histogram 直方图中最大的矩形
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- [LeetCode#84]Largest Rectangle in Histogram
Problem: Given n non-negative integers representing the histogram's bar height where the width of ea ...
- LeetCode 84. Largest Rectangle in Histogram 直方图里的最大长方形
原题 Given n non-negative integers representing the histogram's bar height where the width of each bar ...
- [leetcode]84. Largest Rectangle in Histogram直方图中的最大矩形
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- leetCode 84.Largest Rectangle in Histogram (最大矩形直方图) 解题思路和方法
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- 【LeetCode】84. Largest Rectangle in Histogram 柱状图中最大的矩形(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 单调栈 日期 题目地址: https://leetc ...
- 84. Largest Rectangle in Histogram
https://www.cnblogs.com/grandyang/p/4322653.html 1.存储一个单调递增的栈 2.如果你不加一个0进去,[1]这种情况就会输出结果0,而不是1 3.单调递 ...
随机推荐
- Unity学习之路——主要类
学习https://blog.csdn.net/VRunSoftYanlz/article/details/78881752 1.Component类gameObject:组件附加的游戏对象.组件总是 ...
- 【MySql】Mysql ERROR 1067: Invalid default value for ‘date’ 解决
在给一个表添加字段的时候,忽然发现会报一个date类型的字段的默认值错误,郁闷~ 经过排查,原来是MySQL的配置问题,在wamp下,MySQL 5.7里是没有设置 SQL_MODE 的. 1.my. ...
- Huawei warns against 'Berlin Wall' in digital world
From China Daily Huawei technologies criticized recent registration imposed on the Chinese tech comp ...
- LeetCode(219) Contains Duplicate II
题目 Given an array of integers and an integer k, find out whether there are two distinct indices i an ...
- STM32的IAP方案
from: http://bbs.eeworld.com.cn/thread-294115-1-1.html 几乎所有的同类书籍都介绍综合性的应用示例如“万年历 + 温度显示 + 闹钟响铃 + 计 ...
- linux中的部分宏
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- HDU 4866 Shooting 扫描线 + 主席树
题意: 在二维平面的第一象限有\(n(1 \leq n \leq 10^5)\)条平行于\(x\)轴的线段,接下来有\(m\)次射击\(x \, a \, b \, c\). 每次射击会获得一定的分数 ...
- Django基于Pycharm开发之二 [使用django adminSite]
在使用django自带的adminsite的时候,有以下内容需要做. 1.数据迁移,管理表的创建. 2.启用本地化 (setting.py的配置) 一.数据迁移,默认情况下,安装django之后,dj ...
- day07 类的进阶,socket编程初识
类的静态方法: 正常: 添加静态方法: 就会变成一个函数,不会自动传self 参数,不会调用类的变量和实例的变量 不在需要self 名义上归类管,但是它就是一个单独的函数,不在需要传入self,想怎 ...
- java基础语法中容易出错的细节
1 java中的数字默认类型为int **容易出现类型转换错误 long 定义的数字后面必须有 “l” “L” float 定义的数字后面必须有 “f” “F” java中比int表述范围大的数,不会 ...