LeetCode0085.最大矩形 Go语言AC笔记

 时间复杂度:O(n²)

解题思路

先确定每个元素的左侧连续1的个数(包括本身),记录到left[i][j]数组中,表示矩阵第i-1行第j-1列的元素包括自身左侧有几个连续的1,可以将这个值理解为宽度。

接下来确定这个宽度能上下“走”多远。走多远的意思就是如果维持这个宽度,最高的高度是多少,也就是要找到小于这个宽度的上下边界(上是指下标较小的行,下是指下标最大的行)。对于寻找一列所有元素的上边界,那就从上向下遍历该列元素,用单调栈维护行下标left值大小关系,left值小的行下标在栈底,大的在栈顶,这样每遍历一个元素,都使单调栈中不小于该元素left值的行下标出栈,这样上界就是栈顶元素了,并且再令该元素的行下标入栈;对于寻找下边界也是同理,不过是从下向上遍历,也是left值小的行下标在栈底。

当确定好上下界后,每一个元素维持它的left值宽度能走的最大距离就是上下边界之差再减1,所以最大面积就是高度乘left值宽度。

AC代码

func maximalRectangle(matrix [][]byte) (res int) {
    if len(matrix)==0{
        return res
    }
    m,n:=len(matrix),len(matrix[0])
    left:=make([][]int,m)
    for i:=0;i<m;i++{
        left[i]=make([]int,n)
        if matrix[i][0]=='1'{
            left[i][0]=1
        }
        for j:=1;j<n;j++{
            if matrix[i][j]=='1'{
                left[i][j]=left[i][j-1]+1
            }
        }
    }
    //遍历所有列
    for j:=0;j<n;j++{
        up,down,stk:=make([]int,m),make([]int,m),[]int{}//up,down分别为该列小于该元素left值的上下界
        //确定行下标最大的上界
        for i:=0;i<m;i++{
            //比较单调栈中该列栈顶行的left值
            for len(stk)>0&&left[stk[len(stk)-1]][j]>=left[i][j]{
                stk=stk[:len(stk)-1]
            }
            up[i]=-1//up数组记录该元素的上界
            if len(stk)>0{
                up[i]=stk[len(stk)-1]
            }
            stk=append(stk,i)//将遍历到的每一行入栈
        }
        stk=[]int{}//单调栈必须清空,等待确定下界
        //确定行下标最小的下界
        for i:=m-1;i>=0;i--{
            for len(stk)>0&&left[stk[len(stk)-1]][j]>=left[i][j]{
                stk=stk[:len(stk)-1]
            }
            down[i]=m
            if len(stk)>0{
                down[i]=stk[len(stk)-1]
            }
            stk=append(stk,i)
        }
        for i:=0;i<m;i++{
            height:=down[i]-up[i]-1//能容纳该元素宽度的最大高度就是上下界之差减1
            area:=height*left[i][j]//最大高度乘该元素的宽度就是该元素的最大面积
            if area>res{
                res=area
            }
        }
    }
    return res
}

感悟

研究题解研究了一小时,看了代码才发现比文字简洁多了……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SwithunH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值