LargestRectangleInHistogram_84

LargestRectangleInHistogram_84

题目描述

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

求在该柱状图中,能够勾勒出来的矩形的最大面积。

image.png

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

image.png

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

示例:

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

思路分析

解法1:暴力解法1

首先从处理1个矩形的情况开始,也就是它本身的大小,将这个值记作最大值,然后处理两个矩形的情况,这就有两种情况了,它本身的大小,它和第一个矩形的高度最小值*宽度,将他们与最大值比较,然后是第三个矩形,它就需要计算包括:它自己的大小,它和它前一个勾勒出来的矩形的大小,它和它前两个勾勒出来的矩形大小,然后与最大值进行比较,之后的一次类推。

解法2:暴力解法2

计算一个矩形的大小,我们需要确定的它的长和宽,宽是不好确定的,但是我们可以确定它的高,我们可以从每一个矩形出发,计算以它为高的矩形的最大面积,遍历完所有的矩形之后,最大的矩形面积就出来了

解法3:利用单调栈加哨兵

这个算法的核心思想就是,确定一个矩形以它为高能勾勒出来的最大面积,在遇到第一个比它矮的矩形的时候就已经定下来了,并且我们是先遍历的后确定,满足栈这种数据结构的特点另外,为了在两个端点方便处理,构建了一个新的数组,在数组前后各补充两个0,例如:原数组={2,1,5,6,2,3},更新后的数组={0,2,1,5,6,2,3,0}。并且在一开始就将0入栈

好了,我们可以开始遍历了,从新数组的第1位开始,如果遇到元素它比栈顶的元素大,那么暂时它所能勾勒出来的最大矩形我们是没法确定的,这时候将它的位置入栈,并不是它对应的属性值,它的属性值可以直接通过数组访问,当遇到一个比栈顶元素高度小的矩阵时,这个时候栈顶这个元素所能勾勒出来的最大矩形我们就能确定了,它的高就是栈定元素,宽是当前序号-栈定-1,如果这个时候栈顶还满足大于当前元素,那么则继续弹栈,计算方式与上面相同。

为什么宽度可以这样确定呢?

因为我们的栈是单调的,当前栈顶元素的高度肯定是比之前栈定元素小的,所以肯定可以往那么去勾勒。

Java代码

暴力算法1
//暴力算法
public static int largestRectangle(int[] heights){
    if (heights.length==0)
        return 0;
    int max=heights[0];
    for (int i = 1; i < heights.length; i++) {
        int this_max=heights[i];
        int this_min=heights[i];
        for (int j=i-1;j>=0;j--){
            this_min=Math.min(this_min,heights[j]);
            this_max=Math.max(this_max,(i-j+1)*this_min);
        }
        max=Math.max(max,this_max);
    }
    return max;
}
单调栈加哨兵

哨兵也就是我们添加的那两个0

public static int largestRectangle(int[] heights){
		if (heights.length==0)
            return 0;
        if(heights.length==1)
            return heights[0];
        Deque<Integer> stack=new ArrayDeque<>();
        stack.add(0);
        //添加两个哨兵节点,用于第一个柱体和最后一个柱体的比较
        int[] newHeights=new int[heights.length+2];
        newHeights[0]=0;
        newHeights[newHeights.length-1]=0;
        int maxS=0;
        System.arraycopy(heights,0,newHeights,1,heights.length);
        //对添加了哨兵节点的数组进行遍历
        for (int i = 1; i < newHeights.length; i++) {
            while(newHeights[i]<newHeights[stack.peekLast()]){
                //获取矩形高度,并将已经计算过的元素弹出
                int a=newHeights[stack.pollLast()];
                //获取矩形宽度
                int b=i-stack.peekLast()-1;
                maxS=Math.max(maxS,a*b);
            }
            stack.add(i);
        }
        return maxS;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值