LeetCode 221.最大正方形
確定狀態:
正方形的理解:
如圖所示,對於每個位置(i,j)
,其能確定最大的正方形邊長,其實是(i-1,j-1),(i-1,j),(i,j-1)
三個位置的最大正方形的邊長最小值(類比於:木桶的短板理論,AOE圖中的關鍵路徑)。
狀態: 設f[i][j]
爲所在位置最大正方形的邊長。
轉移方程:
f[i][j]=min{f[i-1][j-1],f[i-1][j],f[i][j-1]}
.
初始條件和邊界
保證數組索引不越界,遍歷從下標1
開始。
最後答案是邊長的平方
class Solution {
public int maximalSquare(char[][] matrix) {
int m=matrix.length;
if(m==0)
return 0;
int n=matrix[0].length;
int [][]f=new int[m+1][n+1];
int res=0;
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(matrix[i-1][j-1]=='1'){
f[i][j]=1+Math.min(f[i-1][j-1],Math.min(f[i][j-1],f[i-1][j]));
res=Math.max(res,f[i][j]);
}
}
}
return res*res;
}
}
優化:
觀察轉移方程:
f[i][j]=min{f[i-1][j-1],f[i-1][j],f[i][j-1]}
,我們發現可以只用一維數組實現:
紅色表示上一行的數據,綠色表示該行數據
因爲計算後上一行f[j]
將被覆蓋,需要t
用來保存上一行f[j]
的值。
這個t
就成爲下一輪的pre
,之前二維數組中的f[i-1][j-1]
進入下一次循環,j++之後:
class Solution {
public int maximalSquare(char[][] matrix) {
int m=matrix.length;
if(m==0)
return 0;
int n=matrix[0].length;
int []f=new int[n+1];
int res=0,t=0,pre=0;
int i,j;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
t=f[j];
if(matrix[i-1][j-1]=='1'){
f[j]=1+Math.min(f[j-1],Math.min(pre,f[j]));
res=Math.max(res,f[j]);
}
else
f[j]=0;
pre=t;
}
}
return res*res;
}
}