Leetcode221. Maximal Square
Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.
Example:
Input:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Output: 4
动态规划
可以认为边长为3的正方形是由若干个边长为2的正方形堆叠得到的,这就是这道题的核心状态转移方程。
一、定义状态:
用 dp[i][j]
表示以 matrix[i][j]
为右下角正方形的最大边长。
二、状态转移方程:
左、上、左上三者取最小,再加上1。
- 图1:受限于左上的0
- 图2:受限于上边的0
- 图3:受限于左边的0
- 数字表示:以此为正方形右下角的最大边长
- 黄色表示:格子 ? 作为右下角的正方形区域
即:dp[i][j] = Min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]) + 1
三、初始化与输出
初始化第一行第一列的dp[i][j] = matrix[i][j] - 0
,输出d[i,j]
。但是为了避免对边的判断处理,在最左侧加上一列 f[i][0] = 0
,在左上边加上一行 f[0][j] = 0
。
public int maximalSquare(char[][] matrix) {
int rows = matrix.length;
if (rows == 0) {
return 0;
}
int cols = matrix[0].length;
int[][] dp = new int[rows + 1][cols + 1];
int maxSide = 0;
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
//因为多申请了一行一列,所以这里下标要减 1
if (matrix[i - 1][j - 1] == '0') {
dp[i][j] = 0;
} else {
dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
maxSide = Math.max(dp[i][j], maxSide);
}
}
}
return maxSide * maxSide;
}
状态压缩
因为更新当前行的时候,只用到前一行的信息,之前的行就没有再用到了,所以我们可以用一维数组,不需要二维矩阵。
public int maximalSquare(char[][] matrix) {
int rows = matrix.length;
if (rows == 0) {
return 0;
}
int cols = matrix[0].length;
int[] dp = new int[cols + 1];
int maxSide = 0;
int pre = 0;//保存左上角的值
for (int i = 1; i <= rows; i++) {
for (int j = 1; j <= cols; j++) {
int temp = dp[j];
if (matrix[i - 1][j - 1] == '0') {
dp[j] = 0;
} else {
dp[j] = Math.min(dp[j - 1], Math.min(dp[j], pre)) + 1;
maxSide = Math.max(dp[j], maxSide);
}
pre = temp;
}
}
return maxSide * maxSide;
}