LeetCode84 柱状图中最大的矩形

题目:给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。在这里插入图片描述
示例:

输入: [2,1,5,6,2,3]
输出: 10
解决思路:
1、求的是面积 所以关注面积=高度宽度
2、最大面积 ==》肯定会用到res=Math.max(res,height
width)
3、总结1和2 得出主要是高度height 和宽度width怎么计算。
3.1 我们想着使用每个柱形作为高度 计算它作为高度时的最大宽度,即它所对应的最大矩形。
3.2 如何找每个柱形作为高度时的宽度呢:
3.2.1 从该柱形往左边延伸, 找到最后一个大于等于该柱形高度的最左边的一个柱。left
3.2.2 从该柱形往右边延伸, 找到最右边的最后一个大于等于该柱形高度的一个柱 right
3.2.3 width= right-left+1;
3.3 总结上述大致思路
3.3.1 首先for遍历数组中每一个柱形
3.3.2 针对每一个柱子 分别向左边延伸 向右边延伸
这个方法是一个暴利方法 时间复杂度O(n^2)
空间复杂度 O(1)

class Solution {
    public int largestRectangleArea(int[] heights) {
        int len = heights.length;
        if(len<=0) return 0;
        if(len==1) return heights[0];
        int res=0;
        for(int i=0;i<len;i++){
            int curHeight=heights[i];
            int left=i;
            while(left>0&&heights[left-1]>=curHeight){
                left--;
            }
            int right=i;
            while(right<len-1&&heights[right+1]>=curHeight){
                right++;
            }
            int curWidth=right-left+1;
            res = Math.max(res,curHeight*curWidth);
        }
        return res;

    }
}

在这里插入图片描述

4、为了优化上述的暴力方法
进一步分析,是否可以边遍历的时候,存储一些信息,
4.1因为存储下标的话 可以通过下标随机访问到数组中的高度值
所以我们一般存储索引
(在下面我想直接引入哨兵的做法, 直接免去我们对栈是否为空的判断)
4.2 以上述的[2,1,5,6,2,3]为例,
首先使用System.arraycopy(height,0,newHeight,1,len),将旧的数组拷贝。newHeight的数组长度为len+2.对于原数组最左边和最右边都各自增加了一个哨兵,因为这两个哨兵的柱高度可以看完0,所以栈中不会出现遍历整个数组之后出现栈不空的情况,同时不会出现栈空的情况,因为栈中第一个值为0, 数组中的值都大于0,所以0不会出栈,栈不会为空。
4.2.1 newHeight=[0,2,1,5,6,2,3,0] 注意 这个是一个单调非递减栈。
直接看
栈以及哨兵的详解

class Solution {
    public int largestRectangleArea(int[] heights) {
        int len=heights.length;
        if(len<=0) return 0;
        if(len==1) return  heights[0];

        int[] newHeight =  new int[len+2];
        Deque<Integer> stack = new ArrayDeque<Integer>();
        newHeight[0]=0;
        System.arraycopy(heights,0,newHeight,1,len);
        heights = newHeight;
        len+=2;
        
        newHeight[len-1]=0;
        
        stack.addLast(0);
        int res=0;
        for(int i=1;i<len;i++){
            while(heights[i]<heights[stack.peekLast()]){
                int curHeight=heights[stack.pollLast()];
                //while(heights[stack.peekLast()]==curHeight){
                    //stack.pollLast();
                //}
                int curWidth=i-stack.peekLast()-1;
                res=Math.max(res, curWidth*curHeight);
            }
            stack.addLast(i);
        }
        return res;

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值