題目描述
給定 n 個非負整數,用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰,且寬度爲 1 。求在該柱狀圖中,能夠勾勒出來的矩形的最大面積。(LeetCode84)
樣例
輸入: [2,1,5,6,2,3]
輸出: 10
題解
單調棧的思想是棧中存放的元素是按照單調遞增或者單調遞減的順序存放的。
- 我們以單調遞減爲例,當壓入棧的元素大於棧頂元素時,那麼對於棧頂元素來說,此時右側離他最近的並且大於棧頂元素的值正是待壓入棧的該元素,而左側離他最近的且大於它的正是在棧中它下一個位置的元素。
- 當數組遍歷完畢之後,棧中還有元素時,此時彈出的元素不是任何數值強迫他彈出那麼它右側離他最近的比他大的元素爲空,左側離他最近比他大的元素正是在棧中相鄰的下一個位置的元素。此時最後彈出的那個元素左爲空,右也爲空。
- 當遇到相等元素壓入時,不需要彈出 而是把下標放在一起,等待下一個壓入的比他大的元素時依次彈出相同的元素,並將右側的值分別設置爲當前壓入的元素。
在本題中我們利用棧存儲元素的下標,按照元素值單調遞增的關係存放。
- 當待壓入的元素 大於棧頂元素時,直接push其下標;
- 當待壓入的元素小於等於棧頂元素時,需要彈出棧頂元素,並計算棧頂元素所能繪製的矩形的面積,該矩形的右邊界即爲待壓入元素的下標,左邊界即爲新棧頂元素的下標(棧不爲空的情況下。若棧爲空,令左邊界爲-1,(右邊界-左邊界-1)*舊棧頂元素的值即爲矩形的面積)
- 當遍歷結束棧中還有元素時,那麼依次彈出棧中元素,每一個元素所構成的矩形的右邊界爲數組的長度,左邊界爲棧中相鄰的下一個元素的值
2的邊界爲(-1,1)
1的邊界爲(-1,6)
5的邊界爲(1,4)
6的邊界爲(2,4)
2的邊界爲(1,6)
3的邊界爲(4,6)
public int largestRectangleArea(int[] heights) {
if(heights==null||heights.length==0)
return 0;
int maxArea=0;
Stack<Integer> stack=new Stack<>();
for(int i=0;i<heights.length;i++) {
while(!stack.isEmpty()&&heights[i]<=heights[stack.peek()]) {
int peek=stack.pop();
int left=stack.isEmpty()?-1:stack.peek();
maxArea=Math.max(maxArea, heights[peek]*(i-left-1));
}
stack.push(i);
}
while(!stack.isEmpty()) {
int peek=stack.pop();
int left=stack.isEmpty()?-1:stack.peek();
maxArea=Math.max(maxArea, heights[peek]*(heights.length-left-1));
}
return maxArea;
}