lintcode:直方图最大矩形覆盖

给出的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;
}
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值