LintCode-直方圖最大矩形覆蓋

直方圖最大矩形覆蓋

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.

histogram

Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

histogram

The largest rectangle is shown in the shaded area, which has area = 10 unit.

分析一下可以發現,在直方圖的某一位置i,對於其左邊任何不低於height[i]的bar的高度height[j],並不會對該位置所構成的最大矩形產生影響。如題目樣例[2,1,5,6,2,3]中,對於位置i=1,無論樣例是[2,1,5,6,2,3]、[1,1,5,6,2,3]還是[5,1,5,6,2,3]都不會影響i=1是的最大矩形面積max=2。
因此只要保存從開始到i-1位置的高度遞增序列,在位置i更新最大矩形max。比較i位置的bar與序列最後元素的高度:
當bar.y>h.back().y時,將bar直接加入序列h;
而bar.y<=h.back().y時,丟棄先前序列中高度小於bar的元素。

注意刪除時忘了j–會跳過一個元素

class Solution {
public:
    /**
     * @param height: A list of integer
     * @return: The area of largest rectangle in the histogram
     */
    struct increase{
        int x,y;
    };
    int largestRectangleArea(vector<int> &height) {
        // write your code here
        vector<increase> h(1);
        h[0].x=-1;
        h[0].y=0;
        int max=0;
        for(int i=0;i<height.size();i++)
        {
            increase t;
            t.x=i;
            t.y=height[i];
            for(int j=0;j<h.size();j++)
            {
                auto s=(i-h[j-1].x)*min(h[j].y,t.y);
                if(s>max)
                {
                    max=s;
                }
                if(h[j].y>=t.y)
                {
                    //delete
                    h.erase(h.begin()+j);
                    j--;
                }
            }
            h.push_back(t);
            auto s=(i-h[h.size()-2].x)*t.y;
            max=s>max?s:max;
        }
        return max;
    }
};

結果超時了,可以看出並不是所有位置都需要計算max。新增的bar是不需要計算max的,因爲後面的bar高度可能高於該bar,因此,在刪除元素時進行最大矩形的計算可以節省時間。
另一方面,只有增加了只有處於高度遞增序列最大值的元素才需要計算並更新最大矩形max,而其之前的最大矩形必定小於該位置的最大矩形。因此加入max_x記錄當前計算過的最大矩陣的下標位置,當刪除元素時,只有當前下標大於max_x的位置才進行計算。

在序列前後分別加入高度爲-1,0的元素以省去判斷過程。兩個高度不能一樣,否則就會變成成未遞增的序列而被刪除。

class Solution {
public:
    /**
     * @param height: A list of integer
     * @return: The area of largest rectangle in the histogram
     */
    struct increase{
        int x,y;
    };
    int largestRectangleArea(vector<int> &height) {
        // write your code here
        vector<increase> h(1);
        h[0].x=-1;
        h[0].y=-1;
        //在序列前加入-1
        height.push_back(0);
        //在序列後加入0
        int max=0;
        //當前最大矩形面積
        int max_x=-1;
        //當前比較過最大矩形的最後下標,注意不能設成0,否則從第二個元素開始算
        for(int i=0;i<height.size();i++)
        {
            increase t;
            t.x=i;
            t.y=height[i];
            while(t.y<=h.back().y)//未遞增
            {
                if(h.back().x>max_x)
                {
                    for(int j=1;j<h.size();j++)
                    {
                        auto s=(h.back().x-h[j-1].x)*h[j].y;
                        if(s>max)
                        {
                            max=s;
                        }
                    }
                    max_x=h.back().x;
                }
                h.pop_back();
            }
            h.push_back(t);
        }
        return max;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章