241009-84 柱状图中最大矩形

56 阅读1分钟

给定 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;
}