84. 柱状图中最大的矩形(java实现)--LeetCode

题目:

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
在这里插入图片描述

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

示例:

输入: [2,1,5,6,2,3]
输出: 10

解法1:暴力

/**
 * 思路:
 * 暴力,双层for
 * 记录最大面积max,和最小柱子的高度
 * 不断向前遍历,找到每个棒子所在范围内的最小值,更新min和area
 *
 * 注意:1根柱子也可以计算面积
 */
    public int largestRectangleArea(int[] heights) {
        int max=0,minHeight;
        for (int i=0;i<heights.length;i++){
            minHeight=heights[i];
            for (int j=i;j<heights.length;j++){
                minHeight=minHeight>heights[j]?heights[j]:minHeight;
                int area = minHeight * (j - i + 1);
                max=max>area?max:area;
            }
        }
        return max;
    }

时间复杂度:On^2

空间复杂度:O1
在这里插入图片描述

解法2:栈实现

/**
 * 思路:
 * 核心思路:
 * 确定每个柱子的左右边界,一旦确定就进行area计算(确定每个棒子最大可能的面积,知道了所有的柱子最大可能面积就能找到柱状图最大面积)
 * 不断的向前遍历数组,我们是一定可以知道的是每个棒子的左边界(左边的棒子已经遍历到),但是棒子的右边界无法确定(右边的棒子还未遍历到)。
 *
 * 栈能很好能实现这个思路
 * 栈中存放初始值-1(方便第一个棒子计算面积),栈中存放的是数组的下标
 * 遍历数组
 * 如果当前值比栈中元素大就入栈(这样当前柱子的左边界就是他们在栈中的下一个元素)
 * 如果当前值比栈中元素小就把栈中元素都出栈!!出栈元素的左右边界相当于确定了(左边界是栈中的下一个元素,右边界就是这个比他小的元素),计算area和max进行比较。之后入栈当前值
 * 遍历完后,清空栈,计算面积:这个时候剩余元素的右边界都是heights.length,左边界依旧是栈中下一个元素
 */
     public int largestRectangleArea(int[] heights) {
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        stack.push(-1);
        int max=0;
        for (int i=0;i<heights.length;i++){
            while (stack.peek()!=-1&&heights[i]<heights[stack.peek()]){
                int bar_heigh=heights[stack.pop()];
                int area=bar_heigh*(i-stack.peek()-1);
                max=area>max?area:max;
            }
            stack.push(i);
        }
        while (stack.peek()!=-1){
            int bar_heigh = heights[stack.pop()];
            int area=bar_heigh*(heights.length-stack.peek()-1);
            max=area>max?area:max;
        }
        return max;
    }

时间复杂度:On

空间复杂度:On在这里插入图片描述

解法3:分治

/**
 * 思路:
 * 核心思路:在最小值的左侧,和右侧才可能出现更大的面积
 * 
 * 分治
 * 终止条件,start>end
 * 找到数组的最小值,求面积
 * 子问题:在左右侧在找最大面积
 */
     public int largestRectangleArea(int[] heights) {
        return divideConquer(0,heights.length-1,heights);
    }

    private int divideConquer(int start, int end, int[] heights) {
        //Terminator
        if (start>end){
            return 0;
        }
        //process current logic
        int min=start;
        for (int i=start;i<=end;i++){
            if (heights[i]<heights[min]){
                min=i;
            }
        }
        int area=heights[min]*(end-start+1);
        //drill down
        return Math.max(area,Math.max(divideConquer(start,min-1,heights),divideConquer(min+1,end,heights)));
        //restore store
    }

时间复杂度:On^2

空间复杂度:O1
在这里插入图片描述

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页