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

题目这道题目算是比较难的了,需要好好解释一下

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

求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述
在这里插入图片描述

输出示例

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

代码一(非常好理解,但是时间复杂度非常大,不使用)

class Solution {
        public static int largestRectangleArea(int[] heights) {
            if (heights.length == 0) {
                return 0;
            }
            if (heights.length == 1) {
                return heights[0];
            }
            //代码的思路非常简单,建立两个数组,nums1和num2;
            //nums1用于保存当前位置i左边第一个小于heights[i]的位置加一,也就是左边最后一个不小于heights[i]的数;
            //nums2用于保存当前位置i右边第一个小于heights[i]的位置加一;
            //例如对于上面的输入,当i等于1时,heights[i]=1,所以nums1[i]=0,这里保存的是对应的位置,也就是heights[0]=2;nums2[i]=2,也就是heights[2]=5;
            int[] nums1=new int[heights.length];
            int[]nums2=new int[heights.length];
            int result=0;
            for(int i=0;i<heights.length;i++){
                int left=i-1;
                int right=i+1;
                while(left>=0&&heights[left]>=heights[i]){
                    left--;
                }
                while(right< heights.length&&heights[right]>=heights[i]){
                  right++;
                }
                    nums1[i]=left+1;
                    nums2[i]=right-1;
            }
            //接下来我们遍历数组,以每一次遍历的heights[i]为高,向左向右取矩形的长,相乘即可
            for(int i=0;i<heights.length;i++){
                result=Math.max(result,heights[i]*(nums2[i]-nums1[i]+1));
            }
            return result;
        }
    }

代码二,上面的代码是极其不推荐的,接下来我们说另一种常规方式,单调栈实现

class Solution {
    public int largestRectangleArea(int[] heights) {
    if(heights.length==0){return 0;}
    //创建一个栈,要时刻保证栈中的元素是单调递增的,栈中保存的是heights中元素对应的下标位置,注意这点。
    Stack<Integer>stack=new Stack<>();
    int result=0;
    //将栈中存入一个标志位,一会会解释作用
    stack.push(-1);
    for(int i=0;i<heights.length;i++){
    //如果当前栈不为空,要注意这里以栈顶是否为-1,判断是否存在元素;
    //且heights[i]小于栈顶元素(前面也说了,要时刻保证栈为单调栈);
    //就需要将栈顶元素拿出,并以栈顶元素在heights中的大小为宽
    //接着我们需要求矩阵对应的长,注意一点矩阵的长并不是单纯的用i去减去弹出栈的元素(栈中保存的是元素在heights中的位置);
    //而是先将栈顶元素弹出,宽等于i减去弹出后的栈的栈顶元素再减一
    //例如heights={3,6,7,5,4};
    //对于前三个元素直接插入栈中,当i等于3,heigths[i]=5时不满足单调递增
    //所以弹出栈中的元素,对于7来说,实际上我们是求以7为宽,且以i等于2这个位置为右边界向左去求对应矩阵的面积;
    //此时将7弹出后,栈顶元素为1(栈中保存的是元素对于在heights的位置),因此长就等于i-stack.peek()-1等于1,这么看确实也等于用i减去原来的栈顶元素(减去7的位置),但是这是在连续递增的前提下才满足的
    //同理6也是这样弹出
    //例如当插入4时,此时栈中元素从顶向下依次为3,0,-1(注意是元素在heights的位置);
    //由于4是小于5的所以我们将栈顶元素弹出,这个时候对应的长度就不在等于单纯的用i减去弹出的元素,
    //因为虽然之前的6和7都弹出了,但是5是小于6和7的,
    //所以我们以5为宽的矩阵真正的长度应该是从6这个位置一直到5这个位置也就是三。
            while(stack.peek()!=-1&&heights[stack.peek()]>heights[i]){
             result=Math.max(result,heights[stack.pop()]*(i-stack.peek()-1));
            }
            stack.push(i);
    }
    //最后栈中若不为空的话,我们还要继续进行判断
    while(stack.peek()!=-1){
        result=Math.max(result,heights[stack.pop()]*(heights.length-stack.peek()-1));
    }
    return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值