Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area.
For example, given the following matrix:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 4.
Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.
题目链接:https://leetcode.com/problems/maximal-square/
public class Solution {
public int maximalSquare(char[][] matrix) {
int n = matrix.length;
if (n == 0) {
return 0;
}
int m = matrix[0].length;
int[][] dp = new int[n + 5][m + 5];
int[][] up = new int[n + 5][m + 5];
int[][] left = new int[n + 5][m + 5];
boolean has = false;
for (int j = 0; j < m; j ++) {
if (matrix[0][j] == '1') {
up[0][j] = 1;
has = true;
}
dp[0][j] = up[0][j];
}
for (int i = 0; i < n; i ++) {
if (matrix[i][0] == '1') {
left[i][0] = 1;
has = true;
}
dp[i][0] = left[i][0];
}
for (int i = 0; i < n; i ++) {
for (int j = 0; j < m; j ++) {
if (i > 0) {
up[i][j] = (matrix[i][j] == '1') ? up[i - 1][j] + 1 : 0;
}
if (j > 0) {
left[i][j] = (matrix[i][j] == '1') ? left[i][j - 1] + 1 : 0;
}
}
}
int ans = has ? 1 : 0;
dp[0][0] = (matrix[0][0] == '1') ? 1 : 0;
for (int i = 1; i < n; i ++) {
for (int j = 1; j < m; j ++) {
if (matrix[i][j] == '1') {
dp[i][j] = Math.min(left[i][j - 1], Math.min(up[i - 1][j], dp[i - 1][j - 1])) + 1;
ans = Math.max(ans, dp[i][j]);
}
}
}
return ans * ans;
}
}
上面的代码写得很丑。。。其实仔细观察可以发现,up和left数组是多余的,dp[i][j] = min(left[i][j - 1], up[i - 1][j], dp[i - 1][j - 1])) + 1这个状态转移方程其实等价于dp[i][j] = min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1])) + 1,原来转移方程的原理是若当前点是'1'且dp[i - 1][j - 1]已经构成了一个边长为k的正方形,若点(i, j)向上向左均可以延伸k个单位长度,那么dp[i][j]可以得到一个边长为k+1的正方形,但其实满足以上三个条件时,显然可以得出dp[i - 1][j]和dp[i][j - 1]都能得到一个边长为k的正方形的结论(画个图可以很清楚的看出),这样两个转移方程就等价了,为了方便处理,将整个矩阵向右下移动一个单位长度,所以其实这样写即可,击败了78%
public class Solution {
public int maximalSquare(char[][] matrix) {
int n = matrix.length;
if (n == 0) {
return 0;
}
int m = matrix[0].length;
int[][] dp = new int[n + 1][m + 1];
int ans = 0;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= m; j ++) {
if (matrix[i - 1][j - 1] == '1') {
dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
ans = Math.max(ans, dp[i][j]);
}
}
}
return ans * ans;
}
}