给定n个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
示例:
输入: [2,1,5,6,2,3]
输出: 10思路:
求构成的最大矩阵面积,对于从序号i~k的范围内的最大矩阵面积,i~k内最小高度为op,则该范围内的最大矩阵面积为(i-k+1)*op
由此可以换思路为,求每个数组元素在某个范围为最小值,其中由此构成的矩阵面积最大。
设某个数组元素为 序号i ,而求对于这个特定的范围内是序号为i的元素最小,可以通过求该元素左边小于该元素的第一个元素,和右边小于序号i的第一个元素,划定范围(当到达左边找不到小于的元素,可以认为从左边到序号i,序号i的元素为最小,右边同理)
例如 序号为 3 的元素 可以通过左边第一小的2和右边的4划定范围,在3~3内6最小
对于序号为i的元素,要快速找到左右边界,可以通过单调栈的形式存储左右边界。
初始化栈,栈存储数组的序号
当栈空或栈顶元素小于或等于当前元素,当前元素的序号进栈(单调递增栈形式)
当栈顶元素大于当前元素时,对于栈顶元素来说,此时可以找到该栈顶元素的左右边界(即左右第一个小于栈顶元素的值),左边界就是栈顶元素出栈后的栈顶,因为栈中元素是单调递增,右边界就为当前元素。
代码:
public int largestRectangleArea(int[] heights) {
if(heights==null||heights.length<=0)
return 0;
Stack<Integer> stack = new Stack<>();
int reuslt = 0;
for(int i=0;i<heights.length;++i){
if(stack.isEmpty()||heights[stack.peek()]<=heights[i]){
stack.add(i);
}
else{
while (!stack.isEmpty()&&heights[stack.peek()]>heights[i]) {
int k = stack.pop();
int left = stack.isEmpty() ? -1 : stack.peek();
int right = i;
reuslt = Integer.max(reuslt, (k - left + right - k - 1) * heights[k]);
}
stack.add(i);
}
}
while (!stack.isEmpty()){
int k = stack.pop();
int left = stack.isEmpty() ? -1 : stack.peek();
int right = heights.length;
reuslt = Integer.max(reuslt, (k - left + right - k - 1) * heights[k]);
}
return reuslt;
}