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;
}
}