leetcode 84. 柱状图中最大的矩形

326 阅读2分钟

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