1 力扣题221:最大正方形
1.1 题目描述
在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。
1.2 思路分析
1.2.1 由回溯为切入点
在这个问题中,由于是在二维数组中进行搜索,首先考虑深搜,深搜的一个经典实现是遍历数组,对每个点进行上下左右搜索,或者在其中再构建辅助数组,但是这种方式在这个场景不成立,因为若以遍历当前元素为左上角进行正方形判断,若判断出正方形辅助数组相应位置清零,此时依然有一些情况被忽略(实际深搜真实数组上,判断在辅助数组上),所以不可取。正确方式是不进行剪枝,即抛弃辅助数组,直接暴力搜索,判断正方形通过不断地加一行和一列来实现
1.2.2 动态规划
涉及到二维数组的场景也可用动态规划来解决。dp[i][j]表示以i,j位置为右下角的最大正方形,状态转移方程为若该位置为0,则为0,若该位置为1,则dp(i,j)=min(dp(i−1,j),dp(i−1,j−1),dp(i,j−1))+1,可用假设证明的思路证明其具有最优子结构
1.3 代码实现
1.3.1 由回溯切入
public int maximalSquare(char[][] matrix) {
//辅助表,正方形新增一行一列进行判断
this.matrix = matrix;
int max_length = 0;
for (int i=0; i<matrix.length; i++) {
for (int j=0; j<matrix[0].length; j++) {
if (matrix[i][j]=='1') {
int length = seek_tangle(i,j);
max_length = Math.max(length,max_length);
}
}
}
return max_length*max_length;
}
public int seek_tangle(int i, int j) {
int length = 1;
while (true) {
if (i+length<matrix.length && j+length<matrix[0].length) {
for (int p=j; p<j+length; p++) {
if (matrix[i+length][p]=='0')
return length;
}
for (int p=i; p<=i+length; p++) {
if (matrix[p][j+length]=='0')
return length;
}
length += 1;
} else
break;
}
return length;
}
1.3.2 动态规划
public int maximalSquare(char[][] matrix) {
int maxSide = 0;
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return maxSide;
}
int rows = matrix.length, columns = matrix[0].length;
int[][] dp = new int[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (matrix[i][j] == '1') {
if (i == 0 || j == 0) {
dp[i][j] = 1;
} else {
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
maxSide = Math.max(maxSide, dp[i][j]);
}
}
}
int maxSquare = maxSide * maxSide;
return maxSquare;
}