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:
给出一个由0,1构成的二维数组,让找出里面最大的正方形的面积
思路:
因为是正方形,长和宽是一样的,较短的一方决定了正方形的边长
假如给一个input
0 1
1 1
依次看(0,0), (0,1), (1,0), (1,1)位置,从(0,0)出发看到这些位置的正方形的边长
(0, 0):input[0][0]=0,不是1,所以不能作为正方形,边长是0
(0, 1):input[0][1] = 1, 它左边是0,当然上面和左斜上方可以想成是0,它本身可以构成边长是1的正方形,所以边长是1
(1, 0):input[1][0] = 1, 它上面是0,当然左边和左斜上方可以想成是0,它本身可以构成边长是1的正方形,所以边长是1
(1, 1):input[1][1] = 1, 虽然说它的上面和左边是1,但是左斜上方是0,限制了它不能构成正方形,左,上,左斜上方最短的边长决定了现在(1,1)位置的正方形边长,(1,1)本身的边长是1,再加上左,上,左斜上方最短的边长,即min(左,上,左斜上方边长)+1 = 1
再比如:
0 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
一次看2✖️2的正方形,所以加了一些空格分开这些值,
可以看到这4个2✖️2的正方形的边长是:
1 2
2 2
因为左,上,左斜上方最短的边长限制了整体(0,0)到右下角的正方形边长,
所以整体正方形的边长是min(左,上,左斜上方边长)+右下角小正方形边长2 = 3
推广:
因为是正方形,长和宽是一样的,较短的一方决定了正方形的边长
用一个dp数组记录从(0, 0)出发到达每个(i,j)能构成的正方形的边长
对每个input[i][j]=1,它的左,上,左斜上方的最短边长决定了当前dp[i][j]
即: dp[i][j] = min(dp[i-1][j -1], dp[i-1][j] ,dp[i][j - 1]) + 1
如果dp[i][j] = 0, 显然是不能构成正方形的,直接=0
因为最大边长不确定出现在哪里,所以在dp计算过程中,保存下最大的边长。
最后结果因为是求面积,所以返回边长*边长
public int maximalSquare(char[][] matrix) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return 0;
}
int[][] dp = new int[matrix.length][matrix[0].length];
int result = 0;
dp[0][0] = matrix[0][0] - '0';
result = dp[0][0];
//left border..
for (int i = 1; i < matrix.length; i++) {
dp[i][0] = matrix[i][0] - '0';
result = Math.max(result, dp[i][0]);
}
//top border..
for (int j = 1; j < matrix[0].length; j++) {
dp[0][j] = matrix[0][j] - '0';
result = Math.max(result, dp[0][j]);
}
for (int i = 1; i < matrix.length; i++) {
for (int j = 1; j < matrix[0].length; j++) {
if (matrix[i][j] == '0') {
dp[i][j] = 0;
} else {
dp[i][j] = Math.min(dp[i - 1][j - 1],
Math.min(dp[i - 1][j], dp[i][j - 1])) + 1;
}
result = Math.max(result, dp[i][j]);
}
}
return (result*result);
}