日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

直方图中最大的矩形(遍历与单调栈)

發布時間:2025/3/15 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 直方图中最大的矩形(遍历与单调栈) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度為 1 。

求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。

以上是柱狀圖的示例,其中每個柱子的寬度為 1,給定的高度為?[2,1,5,6,2,3]。

圖中陰影部分為所能勾勒出的最大矩形面積,其面積為?10?個單位。

示例:

輸入: [2,1,5,6,2,3]
輸出: 10

解法1:一種很好的優化方法,就是遍歷數組,每找到一個局部峰值(只要當前的數字大于后面的一個數字,那么當前數字就看作一個局部峰值,跟前面的數字大小無關),然后向前遍歷所有的值,算出共同的矩形面積,每次對比保留最大值。這里再說下為啥要從局部峰值處理,看題目中的例子,局部峰值為 2,6,3,我們只需在這些局部峰值出進行處理,為啥不用在非局部峰值處統計呢,這是因為非局部峰值處的情況,后面的局部峰值都可以包括,比如1和5,由于局部峰值6是高于1和5的,所有1和5能組成的矩形,到6這里都能組成,并且還可以加上6本身的一部分組成更大的矩形,那么就不用費力氣去再統計一個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;} };

?解法二:單調棧

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

?

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[i] <= heights[st.top()]) {int cur = st.top(); st.pop();res = max(res, heights[cur] * (st.empty() ? i : (i - st.top() - 1)));}st.push(i);}return res;} };

原文:https://www.cnblogs.com/grandyang/p/4322653.html

總結

以上是生活随笔為你收集整理的直方图中最大的矩形(遍历与单调栈)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。