时间复杂度: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
}
感悟
研究题解研究了一小时,看了代码才发现比文字简洁多了……