【leetcode】Largest Rectangle in Histogram

题目信息如下:
1、题目地址为:https://leetcode.com/problems/largest-rectangle-in-histogram/
2、题目意思为:
给定一个非负数组height,代表了矩形的高度(其中矩形宽度为1),求在其中能找出最大的矩形面积。
3、给的例子为: height = [2,1,5,6,2,3]. 输出为:10.示意图如下
图片1

那么下面为正文,讲讲算法的依据(以上面的例子为例):

1、第一个2就没什么讲的了,面积必然为2。
2、当指针指向height[1]的时候,面积有1(也就是自身)和2(如下图)两种可能。
这里写图片描述
3、当指针指向height[2]的时候,如下图所示,有3种面积可能。
这里写图片描述
4、当指针指向height[3]的时候,如下图,有4中可能(图中少画了h[1]-[3]的组合)
这里写图片描述
对比3、4我发现一个有用的规律:
   h[2]的所有面积情况下,都可以加上h[3]所对应的面积。
   也就是,如果指针所在的高度(如h[2]=5)的后面有和自己更高的或者相等的高度(如h[3]=6),那么最大的面积就不可能是指针所在的高度和前面的组合。

这里写图片描述
用下面的图片描述上面的规律,更加贴切。如果要在下图中找最大的面积,必然有高度为6的参与。

另起一段:

这里写图片描述
遇到上面这样的排列,我们会怎么组合?
  看了上面的介绍,你肯定会说,直接1 5 6组合中找最大的,接下来再5 6 2中找最大的面积,最后再看1*4的面积。
  好像有点问题,比如1 5 6 组合中,可能存在1 1 1这样的矩阵,那么为什么不直接讲矩阵拉到2上,也就是说1 1 1 1 = 4的面积哇?
所以总结下我们可以得到下图这样的组合方法:
这里写图片描述
  指针从1开始向后移动,不停的记录信息,直到指针指向2,由于2<6,此时开始计算前面的高度5、6的面积组合,为啥不计算1呢,由于1<2,如果最大面积组合中包含1,那么必然包含2,如上图的红框。最后我们知道,1后面高度都是大于2,那么 面积=(2的下标-1的下标-1)*2的高度。
最后附上代码:

public int largestRectangleArea(int[] height) {
        if(height == null || height.length == 0) return 0;
        int len = height.length;
        Stack<Integer> stack = new Stack<Integer>();
        int max = 0;

        for(int i=0; i<len; i++){
            if(stack.empty() || height[i] >= height[stack.peek()]){//将大于等于栈顶的height入栈,那么中是一个不减序列
                stack.push(i);
            }
            else{//height 小于栈顶的高度
                int left = 0;
                while(!stack.empty() && height[i] < height[stack.peek()]){//直到栈顶的高度小于当前高度
                    left = stack.pop();
                    int cur = height[left] * (stack.empty()?i:i-stack.peek()-1);//入栈是递增,出栈是递减,也就是当前序列高度*出栈了的个数,就是当前的面积
                    if(max < cur){
                        max = cur;
                    }
                }
                stack.push(i);
            }
        }

        int left = 0;
        while(!stack.empty()){//这里用来处理比如[1 2 3 4 5 6 7 8]这样的递增序列或递增子序列
            left = stack.pop();
            int cur = height[left] * (stack.empty()?len:len-stack.peek()-1);
            if(max < cur)
                max = cur;
        }
        return max;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值