在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。
示例:
输入:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
输出: 4
我的思路:我用的是暴力,但是过程有所优化。我找的是遍历过程中该点最大的正方形边长。优化思路是:假设当前节点dp(i,j)为0,那正常后移一位计算dp(i,j+1)。如果do(i,j)==1,标记tmpRes = 1,接下来计算dp(i+1,j+1),如果也是1,那就计算这个点对应的这个列是否都为1,如果有其中一个不是1,那么后移,直接跳到计算dp(i,不为1的这一列后面一列)。如果dp(i+1,j+1)是0,也是这样后移。比如示例先计算dp(0,0)为起点,dp(1,1)为0,因为不管dp(0,1)是什么,以他为起点不会比前面的1大,所以下一个遍历直接跳到dp(0,2)。
代码如下:
public static int maximalSquare(char[][] matrix) {
int matrixRow = matrix.length;
if (matrixRow == 0)
return 0;
int matrixCol = matrix[0].length;
int res = 0;
int[][] matrixInt = new int[matrixRow][matrixCol];
boolean flag = false;
for (int i = 0; i < matrixRow; ++i){
for (int j = 0; j < matrixCol; ++j){
matrixInt[i][j] = Integer.parseInt(String.valueOf(matrix[i][j]));
if (matrixInt[i][j] > 0 )
flag = true;
}
}
if(!flag)
return 0;
res = 0;
int indexRow = 0;
int indexCol = 0;
while (true){
if (indexCol >= matrixCol){
if(res != 0 && res >= matrixRow -1 - indexRow){
break;
}
indexCol = 0;
indexRow++;
}
//这个if判断是否超出坐标,也是终止条件
if(indexRow >= matrixRow)
break;
if (matrixInt[indexRow][indexCol] == 1){
int tmpRes = 1;
int tmpRow = indexRow + 1;
int tmpCol = indexCol + 1;
flag = false;
//如果下一个对角线超出坐标了
if(tmpRow >= matrixRow || tmpCol >= matrixCol){
res = Math.max(res,tmpRes);
if(tmpCol >= matrixCol){
indexCol = 0;
}
indexRow++;
continue;
}
while (matrixInt[tmpRow][tmpCol] == 1){
for (int i = indexRow; i < tmpRow; ++i){
if(matrixInt[i][tmpCol] == 0){
indexCol = tmpCol;
flag = true;
break;
}
}
if (flag)
break;
for (int j = indexCol; j < tmpCol; ++j){
if(matrixInt[tmpRow][j] == 0){
flag = true;
break;
}
}
if (flag)
break;
tmpRow++;
tmpCol++;
tmpRes++;
if(tmpRow >= matrixRow || tmpCol >= matrixCol)
break;
}
if(tmpRow < matrixRow && tmpCol < matrixCol){
if(matrixInt[tmpRow][tmpCol] == 0){
indexCol = tmpCol;
}
}
res = Math.max(res,tmpRes);
}
//可以提前结束的条件
if(res >= matrixCol -1 - indexCol && res != 0){
if(res >= matrixRow -1 - indexRow){
break;
}
indexRow++;
indexCol = 0;
}else {
indexCol++;
}
}
return res * res;
}
官方给出的动态规划思想:关键是找到如何找到局部最优?遍历过程中数组记录该点为右下角时候的最大边长为几。该点的最大长度由其上,左上,左,这三个决定的。值为这三个中最小的加1.如果该点为0,自然是0,不用计算其他。