題目:輸入N個非負整數,分別代表寬度爲1,高度爲整數值得柱子,從柱狀圖裏找出最大四邊形的面積。要求時間複雜度爲O(n),空間複雜度爲O(n)
舉例:輸入數組{1,2,3,1,2,3,1,1,1,1},柱狀圖如圖所示,最大四邊形的面積爲10
對於圖中的任意一條柱形,若是求以該柱形的高度爲高的最大四邊形的面積,需要知道該四邊形的邊界,該最大四邊形的左邊界是左方向第一個小於該柱形高度的柱子的右邊的柱子,右邊界爲右方向第一個小於該柱形高度的柱子。
由於要求時間複雜度爲O(n),因此數組肯定只能遍歷一次。
- 遍歷到第一根柱子,高度爲1,,左邊界是其本身,次時還未確定其右邊界,因此,先不計算以該柱子爲高的最大四邊形的面積。
- 遍歷第二根柱子,高度爲2,左邊界是其本身,次時還未確定其右邊界,因此,先不計算以該柱子爲高的最大四邊形的面積。
- 遍歷至第三根柱子,高度爲3,左邊界是其本身,次時還未確定其右邊界,因此,先不計算以該柱子爲高的最大四邊形的面積。
- 遍歷至第四根柱子,高度爲1,由於其高度小於前一根柱子,因此,第三根柱子的右邊界確定下來,此時開始計算以第三根柱子爲高度的最大四邊形面積。(規律:我們可以注意到前三根柱子是遞增序列,並且前三根柱子的右邊界要麼是遇到的是第四根柱子(右邊遇到的第一根高度下降的柱子),要麼是在往後還未遍歷到的柱子。只要遞增序列後面的第一根高度下降的柱子的高度小於前面的某一根柱子,那麼第一根高度下降的柱子即爲前面某柱子的右邊界。這樣依次計算前面以某根柱子的高度爲高的最大四邊形面積),接下里一次開始計算前面遍歷過得柱子分別對應的最大四邊形面積,先計算第三根柱子對應的最大四邊形面積,然後計算第二根柱子對應的最大四邊形面積,第一根。。。。。
- 。。。。。。。同理繼續遍歷後面的柱子。
以上,在遍歷柱子的過程中,可以觀察到,具有先進後出 的特性,因此該算法可以利用棧來實現,在棧中存放的是數組元素的下標
以下即爲Java 代碼實現:
int maxHistogramArea(int[] height){
int n = height.length;
int max = 0;
Stack<Integer> bars = new Stack<Integer>();
bars.add(-1);//爲了計算相對距離
for(int i = 0;i < n;i++ ){
int pre = bars.peek();
//符合上升序列,加入棧中
if(pre < 0 || height[i] >= height[pre]){
bars.add(i);
}else{
//一旦下降了,開始依次計算前面遍歷過得柱子的面積
pre = bars.pop();
max = Math.max(max,height[pre]*(i-bars.peek()-1));
i--;//還不能確定當前元素是否在上升序列裏
}
}
//還未計算的上升序列的面積
while(bars.peek()!=-1){
int pre = bars.pop();
max = Math.max(max,height[pre]*(n-bars.peek()-1));
}
return max;
}