给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:
输入: heights = [2,1,5,6,2,3]
输出: 10
解释: 最大的矩形为图中红色区域,面积为 10
思路
枚举所有高为h[i]的最大矩形:
他们的宽需要分别找到左边和右边最近的小于h[i]高度的位置,高即为 r - l - 1,从而求出最大面积。
因为需要考虑边界,左边界用-1,右边界用length可以满足r - l - 1算法;
而求每个位置的左右边界可以用单调栈遍历一次得出
public int largestRectangleArea(int[] heights){
//穷举所有高度为i的矩形,高为heights[i],那么宽就是向两边延申左右首次小于heights[i]的位置之差-1
//如果直接暴力循环求解,时间复杂度是O(N^2)
//以O(N)求出每个i左右两边刚好小于它的位置就可以压缩复杂度
ArrayDeque<Integer> stack = new ArrayDeque<>();
int[] left = new int[heights.length];
int[] right = new int[heights.length];
for (int i = 0; i < heights.length; i++) {
//注意等于的也要弹出
while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]){
stack.pop();
}
left[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(i);
}
stack.clear();
//注意for是先执行表达式1和2之后决定走不走循环体,所以要大于等于0
for (int i = heights.length - 1; i >= 0; i--) {
while (!stack.isEmpty() && heights[stack.peek()] >= heights[i]){
stack.pop();
}
right[i] = stack.isEmpty() ? heights.length : stack.peek();
stack.push(i);
}
int res = 0;
for (int i = 0; i < heights.length; i++) {
res = Math.max(res, heights[i] * (right[i] - left[i] - 1));
}
return res;
}