题目描述
给定 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;
}