63
技術社區[雲棲]
龐果網之尋找直方圖中麵積最大的矩形
給定直方圖,每一小塊的height由N個非負整數所確定,每一小塊的width都為1,請找出直方圖中麵積最大的矩形。
如下圖所示,直方圖中每一塊的寬度都是1,每一塊給定的高度分別是[2,1,5,6,2,3]:
那麼上述直方圖中,麵積最大的矩形便是下圖所示的陰影部分的麵積,麵積= 10單位。
請完成函數largestRectangleArea,實現尋找直方圖中麵積最大的矩形的功能,如當給定直方圖各小塊的高度= [2,1,5,6,2,3] ,返回10。
【解析】
使用一個棧來保存輸入柱狀條,每個柱狀條包含兩個信息:(1)柱狀條的高度(height);(2)柱狀條的寬度(width) 。初始寬度均為單位寬度1。
在隨後的入棧和出棧中隨時更改柱狀條的寬度。
(1)當入棧柱狀條的高度大於棧頂柱狀條的高度或者棧為空時,柱狀條入棧;如圖1
(2)當入棧柱狀條的高度小於棧頂柱狀條的高度時,柱狀條出棧,同時計算出棧的柱狀條的麵積,更新最大矩形麵積。同時更新當前柱狀條的寬度。如圖2
(3)當入棧柱狀條的高度等於棧頂柱狀條的高度時,柱狀條出棧,更新當前柱狀條寬度。如圖3
(4)如果最後棧不空,隻剩高度遞增的柱狀條。一個一個出棧,更新最大矩形麵積。每一個柱狀條出棧都要更新前一個柱狀條的寬度。如圖4
寫的不好,勿噴。
【代碼】
/********************************* * 日期:2013-11-24 * 作者:SJF0115 * 題號: 尋找直方圖中麵積最大的矩形 * 來源:https://hero.pongo.cn/Question/Details?ID=58&ExamID=56 * 結果:AC * 來源:龐果網 * 總結: **********************************/ #include<iostream> #include<stack> #include<vector> #include<stdio.h> #include<malloc.h> using namespace std; typedef struct Rec{ int height; int width; }Rec; int LargestRectangleArea(vector<int> &height){ int Max = 0,i; int n = height.size(); //容錯處理 if(n <= 0){ return 0; } Rec *rec = (Rec*)malloc(sizeof(Rec)*n); stack<Rec> stack; //初始化 for(i = 0;i < n;i++){ rec[i].height = height[i]; rec[i].width = 1; } for(i = 0;i < n;i++){ int h = rec[i].height; //如果棧空或者當前高度大於棧頂的矩形高度的時候就壓入棧 if(stack.empty() || h > stack.top().height){ stack.push(rec[i]); } else{ int preWidth = 0; //小於棧頂的矩形高度就彈出棧,更新最大的矩形麵積 while(!stack.empty() && h < stack.top().height){ rec[i].width += stack.top().width; //當前麵積 int currentMax = stack.top().height * (stack.top().width + preWidth); //更新最大值 if(Max < currentMax){ Max = currentMax; } preWidth += stack.top().width; //出棧 stack.pop(); } //等於棧頂的矩形高度 while(!stack.empty() && h == stack.top().height){ rec[i].width += stack.top().width; stack.pop(); } //棧空 if(stack.empty() || h > stack.top().height){ stack.push(rec[i]); } } } //最後棧中隻剩遞增的序列 int width = 0; while(!stack.empty()){ int currentMax = stack.top().height * (stack.top().width + width); if(currentMax > Max){ Max = currentMax; } width += stack.top().width; stack.pop(); } return Max; } int main(){ int i,n,Max,num; while(scanf("%d",&n) != EOF){ vector<int> height; for(i = 0;i < n;i++){ scanf("%d",&num); height.push_back(num); } Max = LargestRectangleArea(height); printf("%d\n",Max); } return 0; }
【方法二】
【解析】
設柱狀圖為非負整數數組A, 則最大矩形的高度必定是數組的某一項height[i]。
設f(i) 為以數組第i項的高度為矩形高度時矩形的最大寬度,則最大矩形為max{f(i)*height[i]} (0 <= i < n)
f(i)本身無法動態規劃,但若將f(i)拆成左右兩部分,則很容易動態規劃求解
令left(i)為以數組第i項為矩形高度時矩形左側最大寬度,
right(i)為以數組第i項為矩形高度時矩形右側最大寬度,
則f(i) = left(i) + right(i) - 1
【代碼】
/********************************* * 日期:2013-11-25 * 作者:SJF0115 * 題號: 尋找直方圖中麵積最大的矩形 * 來源:https://hero.pongo.cn/Question/Details?ID=58&ExamID=56 * 結果:AC * 來源:龐果網 * 總結: **********************************/ #include <stdio.h> int left[100001],right[100001]; int largestRectangleArea(const int *height,int n) { int Max = 0,i,j; //容錯處理 if(height == NULL || n <= 0){ return 0; } left[0] = 1; right[n-1] = 1; //以數組第i項為矩形高度時矩形左側最大寬度 for(i = 1;i < n;i++){ //初始為單位寬度1 left[i] = 1; for(j = i-1;j >= 0;){ if(height[i] <= height[j]){ left[i] += left[j]; //跳到下一個比較對象 j -= left[j]; } else{ break; } } //printf("第%d項左最大寬度:%d\n",i+1,left[i]); } //以數組第i項為矩形高度時矩形右側最大寬度 for(i = n-2;i >= 0;i--){ //初始為單位寬度1 right[i] = 1; for(j = i+1;j < n;){ if(height[i] <= height[j]){ right[i] += right[j]; //跳到下一個比較對象 j += right[j]; } else{ break; } } //printf("第%d項右最大寬度:%d\n",i+1,right[i]); } for(i = 0;i < n;i++){ int currentMax = (left[i] + right[i] - 1) * height[i]; if(Max < currentMax){ Max = currentMax; } } return Max; } //start 提示:自動閱卷起始唯一標識,請勿刪除或增加。 int main() { int height[] = {1,2,3,4,3,4,3,2,1}; int max = largestRectangleArea(height,9); printf("%d\n",max); return 0; } //end //提示:自動閱卷結束唯一標識,請勿刪除或增加。
【測試數據】
{1,2,3,4,3,4,3,2,1} 結果: 15
{3,4,5,6} 結果:12
{2,1,2,1,2,1} 結果:6
{2,1,5,6,2,3}結果:10
{2, 1, 4, 5, 1, 3, 3, 1, 2} 結果:9
最後更新:2017-04-03 14:54:25
上一篇:
給出任意一個正整數,算出大於它的最小不重複數——最高效[2014百度筆試題]
下一篇:
龐果網之楊輝三角的變形
struts中接收數組的表單和ajax兩種形式
阿裏公布百家售假企業黑名單,還挖出了千餘造假工廠
GUI Design Studio 使用教程
讓ATM瘋狂吐錢的黑客死了
IBM WebSphere Application Server V6.1 Fix Pack 37於2011.04.04發布
[JAVA軟件工程師-麵試寶典-2013最新版]
VS2010 Tips: How to change Local Help Library path
在32位的Ubuntu 11.04中為Android NDK r6編譯FFmpeg0.8.1版-Android中使用FFmpeg媒體庫(一)
java.lang.ClassNotFoundException: org.apache.catalina.loader.DevLoader
理解JAVA的傳值方式