題目
給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度爲 1 。求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。
示例
輸入: [2,1,5,6,2,3]
輸出: 10
代碼
暴力法
遍歷每根柱子,以當前柱子 i 的高度作爲矩形的高,那麼矩形的寬度邊界即爲向左找到第一個高度小於當前柱體 i 的柱體,向右找到第一個高度小於當前柱體 i 的柱體。
對於每個柱子我們都如上計算一遍以當前柱子作爲高的矩形面積,最終比較出最大的矩形面積即可。
class Solution {
public int largestRectangleArea(int[] heights) {
int res = 0;
for(int i=0;i<heights.length;i++){
int h = heights[i];
int w = 1;
int j = i-1;
//先遍歷左邊
while(j>=0&&heights[j]>=h){
w++;
j--;
}
j = i+1;
//遍歷右邊
while(j<heights.length&&heights[j]>=h){
w++;
j++;
}
res = Math.max(res,w*h);
}
return res;
}
}
單調棧
我們每遍歷到當前柱體 i 時:
上述寫法中,我們需要再嵌套一層 while 循環來向左找到第一個比柱體 i 高度小的柱體,這個過程是 O(N) 的;
那麼我們可以 O(1) 的獲取柱體 i 左邊第一個比它小的柱體嗎?答案就是單調增棧,因爲對於棧中的柱體來說,棧中下一個柱體就是左邊第一個高度小於自身的柱體
因此遍歷每個柱體,若當前的柱體高度大於等於棧頂柱體的高度,就直接將當前柱體入棧,否則若當前的柱體高度小於棧頂柱體的高度,說明當前棧頂柱體找到了右邊的第一個小於自身的柱體,那麼就可以將棧頂柱體出棧來計算以其爲高的矩形的面積了。
class Solution {
public int largestRectangleArea(int[] heights) {
int[] array = new int[heights.length+2];
System.arraycopy(heights,0,array,1,heights.length);
int res = 0;
//
LinkedList<Integer> stack = new LinkedList<>();
for(int i=0;i<array.length;i++){
while(!stack.isEmpty()&&array[i]<array[stack.peek()]){
/*如果當前柱體高度小於棧頂柱體的高度,
說明當前棧頂柱體找到了右邊的第一個小於自身的柱體,
那麼以它爲高度的矩形面積可求
*/
int index = stack.pop();
res = Math.max(res,(i-stack.peek()-1)*array[index]);
}
/*棧頂柱體爲左邊第一個高度小於當前柱體的柱體,
若當前的柱體高度大於等於棧頂柱體的高度,就直接將當前柱體入棧
*/
stack.push(i);
}
return res;
}
}