数据结构与算法(1)支线任务3——Largest Rectangle in Histogram
题目如下:(https://leetcode.com/problems/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.

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)算法显然会跪(别人试过,我就不作死了……)。
有两类思路,分别如下:
Part One
提示说用栈,然而并没有想出如何使用。看懂别人的思路后再写,总觉得略微无聊……还是在此用自己的话复述一下吧。
(以下所有图片来自http://blog.csdn.net/doc_sgl/article/details/11805519)
题目要求需要找面积最大的矩形,这个矩形的高为直方图中某柱高,我们可以认为矩形是由一个柱向两侧扩展得到的。
题中的直方图可以形象地理解为“波”,在一个波峰附近第一个高度下降的柱(下图中的t)会限制其左侧比它高的柱(记某柱为z)形成矩形的宽度,又由于t是该波峰第一个下降的柱形,故左侧比它高的柱z形成的矩形宽度为t与z横坐标之差(由于后续操作形成的波并不是连续的柱,此处实际上应为t-z前一个柱横坐标-1),这样就得到了一个矩形面积。
如上操作后,柱z已经完成了它的使命(已经求出由它形成的矩形的面积,左右的矮柱也不需要它的高度),当t左侧所有高柱都完成使命后,t成了相对高的柱,可以看作与前面的更矮的柱又在形成一个又矮又宽的波峰(图中阴影),遇到更矮的i之后,重复前面的操作即可得到所有柱生成的矩形的面积。

于是,我们可以用栈保存一串连续上升的柱(波上升的部分),当遇到矮柱时,求前面每个高柱形成的矩形的面积,然后将这个没用的高柱弹出。最后将矮柱压入,作为下一个波的上升部分。这个过程扫描一遍,算法复杂度为O(n)。
/************************如果觉得上面写的清晰可以忽略下面的部分**************************/
针对样例输入,可以进行如下分析:
1.将柱0压栈,。
2.柱1更矮,求柱0形成的矩形面积,将柱1压栈。
3.柱1柱2柱3高度递增,进栈。
4.柱4比2,3矮:柱3求面积,出栈;柱2求面积,出栈。

5.柱4柱5进栈。
6.最后求栈中剩余柱形成矩形的面积(相当于最后有一个高度为0的柱,使其前面的柱出栈)。
(似乎应该在这里再说一下,以上所有图片来自http://blog.csdn.net/doc_sgl/article/details/11805519 )//2015/11/13日补
/************************懂了上面,下面的代码其实不重要了**************************/
class Solution {
public:
int largestRectangleArea(vector<int>& height) {
height.push_back(); //使最后栈中剩余柱出栈
stack<int> serHeight; //储存高度递增的柱的栈
int maxArea = ; //最大面积
int curArea = ; //当前矩形面积
for (int i = ; i < height.size(); i++)
{
if (serHeight.empty() || height[serHeight.top()] <= height[i]) //高度上升,进栈
{
serHeight.push(i);
}
else
{
//将高矩形出栈,求其生成的矩形面积
while (height[serHeight.top()] > height[i])
{
int cur = serHeight.top();
serHeight.pop();
if (serHeight.empty())
{
curArea = height[cur] * i;
maxArea = (maxArea > curArea) ? maxArea : curArea;
break;
}
curArea = height[cur] * (i - serHeight.top() - );
maxArea = (maxArea > curArea) ? maxArea : curArea;
}
serHeight.push(i);
}
}
return maxArea;
}
};
Part Two
一个更容易想到的思路是先判断每个柱左右两边不比它矮的最远柱,然后可以更容易地算出由当前柱形成的矩形面积。
利用动态规划的思想,可以利用前面已确定的最远高柱更新当前需要找的柱。比如下面代码中若l[i]左边的l[i]-1比i还要高,那么可以用l[l[i] - 1]更新l[i],这样可以加快查找高柱的速度。
class Solution {
public:
int largestRectangleArea(vector<int>& height) {
int maxArea = ; //最大面积
int curArea = ; //当前面积
int s = height.size(); //柱形个数
int *l = new int[s]; //储存不比当前柱矮的最左端柱
int *r = new int[s]; //储存不比当前柱矮的最右端柱
//先找储存不比当前柱矮的最左端柱
for (int i = ; i < s; i++)
{
l[i] = i; //自己不比自己矮
//利用已存过的l[i]判断是否找到最左端
while (l[i] && height[l[i] - ] >= height[i])
{
l[i] = l[l[i] - ];
}
}
//再找储存不比当前柱矮的最右端柱
for (int i = s - ; i >= ; i--)
{
r[i] = i;
while ((r[i] - s + ) && height[r[i] + ] >= height[i])
{
r[i] = r[r[i] + ];
}
}
//计算由当前柱生成的矩形面积,更新最大面积
for (int i = ; i < s; i++)
{
curArea = height[i] * (r[i] - l[i] +);
maxArea = (maxArea > curArea) ? maxArea : curArea;
}
return maxArea;
}
}
附:
日常膜:http://www.cnblogs.com/lustralisk/p/branch-3.html
生日快乐:http://blog.sina.com.cn/s/blog_1495db3970102w3f8.html
数据结构与算法(1)支线任务3——Largest Rectangle in Histogram的更多相关文章
- LeetCode 笔记系列 17 Largest Rectangle in Histogram
题目: Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar he ...
- 【LeetCode】84. Largest Rectangle in Histogram
Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...
- Maximal Rectangle&Largest Rectangle in Histogram
这两天在做leetcode的题目,最大矩形的题目以前遇到很多次了,一直都是用最笨的方法,扫描每个柱子,变换宽度,计算矩形面积,一直都以为就这样O(n2)的方法了,没有想到居然还有研究出了O(n)的算法 ...
- Largest Rectangle in Histogram及二维解法
昨天看岛娘直播解题,看到很经典的一题Largest Rectangle in Histogram 题目地址:https://leetcode.com/problems/largest-rectangl ...
- 47. Largest Rectangle in Histogram && Maximal Rectangle
Largest Rectangle in Histogram Given n non-negative integers representing the histogram's bar height ...
- leetcode Largest Rectangle in Histogram 单调栈
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4052343.html 题目链接 leetcode Largest Rectangle in ...
- 关于LeetCode的Largest Rectangle in Histogram的低级解法
在某篇博客见到的Largest Rectangle in Histogram的题目,感觉蛮好玩的,于是想呀想呀,怎么求解呢? 还是先把题目贴上来吧 题目写的很直观,就是找直方图的最大矩形面积,不知道是 ...
- leetcode之Largest Rectangle in Histogram
问题来源:Largest Rectangle in Histogram 问题描述:给定一个长度为n的直方图,我们可以在直方图高低不同的长方形之间画一个更大的长方形,求该长方形的最大面积.例如,给定下述 ...
- LeetCode之“动态规划”:Maximal Square && Largest Rectangle in Histogram && Maximal Rectangle
1. Maximal Square 题目链接 题目要求: Given a 2D binary matrix filled with 0's and 1's, find the largest squa ...
随机推荐
- 5-Spark高级数据分析-第五章 基于K均值聚类的网络流量异常检测
据我们所知,有‘已知的已知’,有些事,我们知道我们知道:我们也知道,有 ‘已知的未知’,也就是说,有些事,我们现在知道我们不知道.但是,同样存在‘不知的不知’——有些事,我们不知道我们不知道. 上一章 ...
- Emgu学习手册
作为opencv的c#封装库.emgu可以满足基本的图像处理功能,经过测试,效果还可以,主要用于windows窗体应用程序的开发,或者wpf,你可以用来做ocr,也可以用来做人脸识别或者可以用来做定位 ...
- zookeeper的安装(图文详解。。。来点击哦!)
zookeeper的安装(图文详解...来点击哦!) 一.服务器的配置 三台服务器: 192.168.83.133 sunshine 192.168.83.134 sunshineMin 19 ...
- C语言中内存的申请函数
C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等. alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且 ...
- 1 error C4996: 'pcl::SAC_SAMPLE_SIZE':
使用PCL1.8 中使用粗配准拼接 错误 1 error C4996: 'pcl::SAC_SAMPLE_SIZE': This map is deprecated and is kept onl ...
- 【引】runtime全解析,P2:关于Class 和 MetaClass
几个基本的概念: id,id的定义是,typedef struct objc_object { Class isa;} *id; id是指向struct objc_object的一个指针.这个意思是, ...
- case when then else end 的用法
case when then end 改语句的执行过程是:将case后面表达式的值与各when子句中的值进行比较,如果两者相等,则返回then后的表达式的值,然后跳出case语句,否则返回else子句 ...
- unity官方换装教程Character Customization 学习笔记
1. 下载示例demo,可以直接从AssetsStore上下载,但是速度比较慢,我在github上找了一个据说支持unity5.x的. 链接:https://github.com/spacebeagl ...
- Apache-Jemeter web性能测试工具使用
Jmeter是一款java开源的性能测试软件. 要使用该工具进行性能测试,首先需要下载该工具到你的电脑,接着配置java开发环境以及Jmeter环境.搭建完成之后,OK,我们就可以进行测试了. 测试第 ...
- 顶点缓存对象(VBO)
创建VBO 绘制VBO 更新VBO 实例 GL_ARB_vertex_buffer_object扩展致力于提供顶点数组与显示列表的优势来提升OpenGL效率,同时避免它们实现上的不足.顶点缓存对象(V ...