lintcode:直方图最大矩形覆盖
2016-07-28 15:30
274 查看
给出的n个非负整数表示每个直方图的高度,每个直方图的宽均为1,在直方图中找到最大的矩形面积。
以上直方图宽为1,高度为[2,1,5,6,2,3]。
最大矩形面积如图阴影部分所示,含有10单位
样例
给出 height = [2,1,5,6,2,3],返回 10
(1)
暴力破解法的思路:求出所有矩阵的面积,可以用右边界和左边界之差,乘以两边界之间的最小高度。(计算最大面积,则需要从左向右遍历所有点作为右边界),从第一个索引开始,记为i,另外一个索引从i开始向右移动,记为j,找出在
[ i .. j] 范围内最低的高度,记为H,那么面积等于 H(j-i+1)遍历完以后找出最大的面积即可。
//但是这样会超时
(2)用栈存储单调递增正序列的下标,与暴力破解法不同之处:它计算的矩阵的面积的右边界是局部的最高点(每次用i-1来表示,因为i是比栈顶元素高度小的下标,所以i-1就是局部最高点的下标),左边界就是从栈顶到栈底各元素的下标(注意下标相同时表示矩阵的宽是1),矩阵的高度就是栈顶到栈底的各个元素的高,用一个max记录最大矩形面积,每次求出一个最大面积就与max比较一次。到最后就得到最大面积。还要注意的是遍历的点i对应的最大矩形,是stack.pop(),也就是它的前一个点i-1作为右边界时的最大矩形,所以i要循环到height.length。当i循环到height.length()时,若栈中还有元素,就还要进行计算矩阵面积,还有要注意,计算矩形宽度的时候,要考虑最高点弹出栈后栈是否为空:如果是,那么宽度w应该赋值i(因为本轮的栈顶一定比上一次的局部峰值小,所以应该取全长)。其它情况下,w
= i-1-stack.top()。
大概过程见代码注释:
以上直方图宽为1,高度为[2,1,5,6,2,3]。
最大矩形面积如图阴影部分所示,含有10单位
样例
给出 height = [2,1,5,6,2,3],返回 10
(1)
暴力破解法的思路:求出所有矩阵的面积,可以用右边界和左边界之差,乘以两边界之间的最小高度。(计算最大面积,则需要从左向右遍历所有点作为右边界),从第一个索引开始,记为i,另外一个索引从i开始向右移动,记为j,找出在
[ i .. j] 范围内最低的高度,记为H,那么面积等于 H(j-i+1)遍历完以后找出最大的面积即可。
//但是这样会超时
int findmin(vector<int> &height,int x,int y){ if(x==y) return x; int minh=x; for(int i=x+1;i<=y;i++) { if(height[minh]>height[i]) minh=i; } return minh; } int largestRectangleArea(vector<int> &height) { int max=0,s=0; for(int i=0;i<height.size();i++) { for(int j=i;j<height.size();j++) //注意单个矩阵的面积也要计算,所以重从=i开始 { int h=findmin(height,i,j); s=(j-i+1)*height[h]; if(s>max) max=s; } } return max; }
(2)用栈存储单调递增正序列的下标,与暴力破解法不同之处:它计算的矩阵的面积的右边界是局部的最高点(每次用i-1来表示,因为i是比栈顶元素高度小的下标,所以i-1就是局部最高点的下标),左边界就是从栈顶到栈底各元素的下标(注意下标相同时表示矩阵的宽是1),矩阵的高度就是栈顶到栈底的各个元素的高,用一个max记录最大矩形面积,每次求出一个最大面积就与max比较一次。到最后就得到最大面积。还要注意的是遍历的点i对应的最大矩形,是stack.pop(),也就是它的前一个点i-1作为右边界时的最大矩形,所以i要循环到height.length。当i循环到height.length()时,若栈中还有元素,就还要进行计算矩阵面积,还有要注意,计算矩形宽度的时候,要考虑最高点弹出栈后栈是否为空:如果是,那么宽度w应该赋值i(因为本轮的栈顶一定比上一次的局部峰值小,所以应该取全长)。其它情况下,w
= i-1-stack.top()。
大概过程见代码注释:
class Solution { public: /* * @param height: A list of integer * @return: The area of largest rectangle in the histogram / int largestRectangleArea(vector &height) { int maxh=0; stackst; //存放递增高度序列的下标 for(int i=0;i<=height.size();i++) //用i遍历全部数组 { int nowh= (i == height.size()) ? 0 : height[i]; //若下标为height.size()时,其高度置为0 while( !st.empty() && nowh <= height[st.top()] ) //若当前的高度小于或等于栈顶的高度时 { int h=height[st.top()]; //矩阵的高度为栈顶元素的高度 ///////这个很重要//// st.pop(); //将栈顶元素弹出 //要先将栈顶元素弹出,因为若左边界元素是栈底元素长度要取数组全长 //而不是当前长度到栈顶的长度 int w; if(st.empty()) //若此时栈空 w=i; //取全部长度,而不应该取 else //否则宽度为i-1-st.top(); w=i-1-st.top(); maxh=max(maxh,w*h); //记录下最大面积 }//执行完这个循环后栈为空,或栈顶元素的高度小于i的高度 st.push(i); //将i再压入栈中 } return maxh; } };
相关文章推荐
- ls的详细用法
- 读书笔记二——第一章《面向服务的体系架构SOA》下
- 5-43 字符串关键字的散列映射
- AndroidStudio导入XlistView步骤
- Guava学习之Lists
- Android安全机制(三)
- ajax提交
- 约瑟夫问题(关于小猴)
- 基础命令
- 【算法杂谈】各种最短路算法模板
- jenkins持续集成工具
- 整数中1 的个数
- python map函数
- 【C++学习之路】解决:无法查找或打开 PDB 文件
- 求字符串中最长无重复字符的子串
- Hbase基本概念
- Tomcat6 启动时 Cannot assign requested address: JVM_Bind
- ArcGis Engine 要素折点转点的代码实现
- 内部类
- 自定义及发布一个webService服务