您的位置:首页 > 其它

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)遍历完以后找出最大的面积即可。


//但是这样会超时


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;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: