溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C++怎么實現(xiàn)直方圖中最大的矩形

發(fā)布時間:2022-03-28 10:22:13 來源:億速云 閱讀:231 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“C++怎么實現(xiàn)直方圖中最大的矩形”,在日常操作中,相信很多人在C++怎么實現(xiàn)直方圖中最大的矩形問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C++怎么實現(xiàn)直方圖中最大的矩形”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

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.

C++怎么實現(xiàn)直方圖中最大的矩形

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

C++怎么實現(xiàn)直方圖中最大的矩形

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.

這道題讓求直方圖中最大的矩形,剛開始看到求極值問題以為要用DP來做,可是想不出遞推式,只得作罷。這道題如果用暴力搜索法估計肯定沒法通過OJ,有一種很好的優(yōu)化方法,就是遍歷數(shù)組,每找到一個局部峰值(只要當(dāng)前的數(shù)字大于后面的一個數(shù)字,那么當(dāng)前數(shù)字就看作一個局部峰值,跟前面的數(shù)字大小無關(guān)),然后向前遍歷所有的值,算出共同的矩形面積,每次對比保留最大值。這里再說下為啥要從局部峰值處理,看題目中的例子,局部峰值為 2,6,3,我們只需在這些局部峰值出進(jìn)行處理,為啥不用在非局部峰值處統(tǒng)計呢,這是因為非局部峰值處的情況,后面的局部峰值都可以包括,比如1和5,由于局部峰值6是高于1和5的,所有1和5能組成的矩形,到6這里都能組成,并且還可以加上6本身的一部分組成更大的矩形,那么就不用費力氣去再統(tǒng)計一個1和5處能組成的矩形了。代碼如下:

解法一: 

// Pruning optimize
class Solution {
public:
    int largestRectangleArea(vector<int> &height) {
        int res = 0;
        for (int i = 0; i < height.size(); ++i) {
            if (i + 1 < height.size() && height[i] <= height[i + 1]) {
                continue;
            }
            int minH = height[i];
            for (int j = i; j >= 0; --j) {
                minH = min(minH, height[j]);
                int area = minH * (i - j + 1);
                res = max(res, area);
            }
        }
        return res;
    }
};

后來又在網(wǎng)上發(fā)現(xiàn)一種比較流行的解法,是利用棧來解,可參考其他文檔,但是經(jīng)過仔細(xì)研究,其核心思想跟上面那種剪枝的方法有異曲同工之妙,這里維護(hù)一個棧,用來保存遞增序列,相當(dāng)于上面那種方法的找局部峰值。我們可以看到,直方圖矩形面積要最大的話,需要盡可能的使得連續(xù)的矩形多,并且最低一塊的高度要高。有點像木桶原理一樣,總是最低的那塊板子決定桶的裝水量。那么既然需要用單調(diào)棧來做,首先要考慮到底用遞增棧,還是用遞減棧來做。我們想啊,遞增棧是維護(hù)遞增的順序,當(dāng)遇到小于棧頂元素的數(shù)就開始處理,而遞減棧正好相反,維護(hù)遞減的順序,當(dāng)遇到大于棧頂元素的數(shù)開始處理。那么根據(jù)這道題的特點,我們需要按從高板子到低板子的順序處理,先處理最高的板子,寬度為1,然后再處理旁邊矮一些的板子,此時長度為2,因為之前的高板子可組成矮板子的矩形 ,因此我們需要一個遞增棧,當(dāng)遇到大的數(shù)字直接進(jìn)棧,而當(dāng)遇到小于棧頂元素的數(shù)字時,就要取出棧頂元素進(jìn)行處理了,那取出的順序就是從高板子到矮板子了,于是乎遇到的較小的數(shù)字只是一個觸發(fā),表示現(xiàn)在需要開始計算矩形面積了,為了使得最后一塊板子也被處理,這里用了個小 trick,在高度數(shù)組最后面加上一個0,這樣原先的最后一個板子也可以被處理了。由于棧頂元素是矩形的高度,那么關(guān)鍵就是求出來寬度,那么跟之前那道 Trapping Rain Water 一樣,單調(diào)棧中不能放高度,而是需要放坐標(biāo)。由于我們先取出棧中最高的板子,那么就可以先算出長度為1的矩形面積了,然后再取下一個板子,此時根據(jù)矮板子的高度算長度為2的矩形面積,以此類推,知道數(shù)字大于棧頂元素為止,再次進(jìn)棧,巧妙的一比!關(guān)于單調(diào)棧問題可以參見博主的一篇總結(jié)帖 LeetCode Monotonous Stack Summary 單調(diào)棧小結(jié),代碼如下:

解法二: 

class Solution {
public:
    int largestRectangleArea(vector<int> &height) {
        int res = 0;
        stack<int> st;
        height.push_back(0);
        for (int i = 0; i < height.size(); ++i) {
            if (st.empty() || height[st.top()] < height[i]) {
                st.push(i);
            } else {
                int cur = st.top(); st.pop();
                res = max(res, height[cur] * (st.empty() ? i : (i - st.top() - 1)));
                --i;
            }     
        }
        return res;
    }
};

我們可以將上面的方法稍作修改,使其更加簡潔一些:

解法三:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int res = 0;
        stack<int> st;
        heights.push_back(0);
        for (int i = 0; i < heights.size(); ++i) {
            while (!st.empty() && heights[st.top()] >= heights[i]) {
                int cur = st.top(); st.pop();
                res = max(res, heights[cur] * (st.empty() ? i : (i - st.top() - 1)));
            }
            st.push(i);
        }
        return res;
    }
};

到此,關(guān)于“C++怎么實現(xiàn)直方圖中最大的矩形”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI