题目:
给定一个M*N的矩阵,在这个矩阵中,只有0和1两种值,返回边框全是1的最大正方形的边长长度。
例如:
[0, 1, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 1, 1, 0, 1],
[0, 1, 1, 1, 1],
[0, 1, 0, 1, 1]
其中,边框全是1的最大正方形的大小为4。
解析:
1.正方形边长为0<=size<=Math.min(rows,cols);
2.边长为size时,左上角的坐标范围为 0<=i<=rows-size,0<=j<=cols-size;
3.使用预处理矩阵right和down,空间换时间,right[i][j]保存matrix[i][j]包括自己往右边有多少个1,同理down[i][j]。
3.对每一个左上角的边长为size的矩形判断边上是否全为1,发现有满足的直接返回当前size。
public int findLength(int[][] matrix)
{
if(matrix == null||matrix.length == 0||matrix[0].length == 0)
return 0;
int rows=matrix.length;
int cols=matrix[0].length;
int[][] right=new int[rows][cols];
int[][] down=new int[rows][cols];
setRightAndDown(matrix,right,down);//预处理矩阵right和down;
for(int size=Math.min(rows, cols) ; size > 0 ; size-- )
{
if(has_size(size,right,down))
return size;
}
return 0;
}
//边长为size的边上为全1的矩形是否存在
public boolean has_size(int size,int[][] right,int[][] down)
{
int rows=right.length;
int cols=right[0].length;
for(int i=0;i<=rows-size;i++)
{
for(int j=0;j<=cols-size;j++)
{
if(right[i][j]>=size&&down[i][j]>=size&&right[i+size-1][j]>=size&&down[i][j+size-1]>=size)
return true;
}
}
return false;
}
//预处理例程
public void setRightAndDown(int[][] matrix,int[][] right,int[][] down)
{
int rows=matrix.length;
int cols=matrix[0].length;
if(matrix[rows-1][cols-1] == 1)
{
right[rows-1][cols-1]=1;
down[rows-1][cols-1]=1;
}
//right col
for(int i=rows-2;i>=0;i--)
{
if(matrix[i][cols-1] == 1)
{
right[i][cols-1]=1;
down[i][cols-1]=down[i+1][cols-1]+1;
}
}
//end row
for(int j=cols-2;j>=0;j--)
{
if(matrix[rows-1][j] == 1)
{
down[rows-1][j]=1;
right[rows-1][j]=right[rows-1][j+1]+1;
}
}
//general
for(int i=rows-2;i>=0;i--)
{
for(int j=cols-2;j>=0;j--)
{
if(matrix[i][j] == 1)
{
right[i][j]=right[i][j+1]+1;
down[i][j]=down[i+1][j]+1;
}
}
}
}