221. 最大正方形
题目
描述
给定一个由 '0' 和 '1' 组成的2维矩阵,返回该矩阵中最大的由 '1' 组成的正方形的面积。输入的矩阵是字符形式而非数字形式。
链接http://https://www.nowcoder.com/practice/0058c4092cec44c2975e38223f10470e
思路
定义 DP 数组:设 dp[i][j] 表示以 (i,j) 为右下角的最大正方形的边长。
状态转移方程:若当前位置 matrix[i][j] == '1',则 dp[i][j] 由其上方、左方、左上方三个位置的 dp 值决定:
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
实际上是一个扩展判定填表的过程
定义右上角、左上角、左下角均可,就是需要编写代码的时候控制好循环变量填表计算。
如左上角最大正方形
dp[i][j] = min(dp[i][j+1], dp[i+1][j], dp[i+1][j+1]) + 1
完整代码
public class Solution {
public int maximalSquare(char[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int rows = matrix.length;
int cols = matrix[0].length;
int[][] dp = new int[rows][cols];
int maxSide = 0; // 记录最大正方形的边长
// 初始化第一行和第一列
for (int i = 0; i < rows; i++) {
if (matrix[i][0] == '1') {
dp[i][0] = 1;
maxSide = Math.max(maxSide, dp[i][0]);
}
}
for (int j = 0; j < cols; j++) {
if (matrix[0][j] == '1') {
dp[0][j] = 1;
maxSide = Math.max(maxSide, dp[0][j]);
}
}
// 填充dp数组的其他位置
for (int i = 1; i < rows; i++) {
for (int j = 1; j < cols; j++) {
if (matrix[i][j] == '1') {
// 取上方、左方、左上方的最小值,加1
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]);
} else {
dp[i][j] = 0;
}
}
}
return maxSide * maxSide; // 返回面积
}
}