在一个由0和1组成的二维矩阵内,寻找只包含1的最大正方形,并返回其面积。
例如,给出如下矩阵:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
返回 4.
这道题仍然是双重循环遍历二维数组,因为要把所有点都作为左上顶点判断,但是判断的时候可以做一些处理:
- 用正方形边长来判断局部是否全1正方形,比如对于坐标[i,j],边长为1时,只需要判断matrix[i,j]==’1’即可,如果是’1’,接下来边长变为2,这时候不是遍历所有4个元素,而是遍历右边加上的一列,以及下边加上的一行是否全1即可。
- 一旦扫描新增列或者新增行中有0,那么以此坐标[i,j]作为左上顶点的扫描就可以结束了,此时将[i,j+1]作为左上顶点开始扫描,而这时候有一个可以避免重复扫描的窍门:由于[i,j+1]是[i,j]右移一位,那么当[i,j]时最大边长是len的时候,[i,j+1]时的最小边长肯定至少是len-1了,不需要从边长为1开始重新扫描
public int maximalSquare(char[][] matrix) {
int max = 0;
for(int i=0;i<matrix.length;i++){
int lastLen = 1;
for(int j=0;j<matrix[0].length;j++){//横向遍历时用上一轮lastlen正方形边长剪枝
if(matrix[i][j] == '1'){
int len = Math.max(lastLen, 2);
max = Math.max(max, 1);
while(j+len-1 < matrix[0].length && i+len-1 < matrix.length){//横向纵向都不能越界
//判断正方形是否全1
boolean allOne = true;
for(int row = i;row<i+len;row++){//原有正方形基础上加上最后一列
if(matrix[row][j+len-1] == '0'){
allOne = false;
break;
}
}
if(allOne){//原有正方形基础上加上最后一横排
for(int col = j;col<j+len;col++){
if(matrix[i+len-1][col] == '0'){
allOne = false;
break;
}
}
}
if(allOne){
int sum = len*len;
max = sum > max? sum : max;
}
else{
break;
}
len++;
}
lastLen = len-1;
}
}
}
return max;
}