给一个2维的矩阵,里面的值为‘0’,‘1’, 找到都是1的最大的正方形的面积。
这是一道可以用动态规划来解决的问题。
1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0
比如这个矩阵的最大的正方形的边长为2,返回面积4.
我们将某个坐标 (i, j )下能够构成的正方形的边长记为cache[ i ] [ j ]。
我们先来看 (0,0), (0,1), (0,2), (0,3) 这些坐标下,值为1,那么能够构成边长为1的;值为0的,不能构成正方形。
同样的,对于(1,0), (2,0), (3,0)这些坐标下,能够构成1, 1, 1的正方形。
所以,我们得到一个base情况下的结果,即第一行,第一列的坐标下,cache[ i ] [ j ] = 对应 matrix 中的值。
再看中间点的情况。
看(1,1)坐标下,它的值是0,那么显然不能构成正方形。
所以,我们来看坐标下的值为1的,比如,(2,1)坐标下的。
截取一部分来看:
[1 0]
[1 0]
[1 1]
它的上面为0,它只能自己构成正方形,边长 = 1。
于是,可以得到一个更为general的推论:
如果某个坐标的值为1,那么cache[ i ] [ j ] = min ( cache[ i ] [ j - 1] ,cache[ i - 1 ] [ j ] ,cache[ i - 1 ] [ j - 1 ] )+ 1
最终,我们将上面的思考整理一下,可以得到:
1. 对于第一行 (j = 0),第一列 (i = 0),这些边缘的,cache[ i ] [ j ] = matrix[ i ] [ j ]
2. i > 0 && j > 0 :
if matrix[ i ][ j ] = 0, cache[ i ] [ j ] = 0 ;
if matrix[ i ][ j ] = 1, cache[ i ] [ j ] = min ( cache[ i ] [ j - 1] ,cache[ i - 1 ] [ j ] ,cache[ i - 1 ] [ j - 1 ] )+ 1 .
复杂度:
时间复杂度 :O(m * n)
空间复杂度:O (m * n)
代码:
public int maximalSquare(char[][] matrix) {
int m = matrix.length;
if (m == 0) {
return 0;
}
int n = matrix[0].length;
int[][] cache = new int[m][n];
int maxLength = 0;
//base cases
for (int i = 0; i < m; i++) {
cache[i][0] = matrix[i][0] - '0';
maxLength = Math.max(maxLength, cache[i][0]);
}
for (int j = 0; j < n; j++) {
cache[0][j] = matrix[0][j] - '0';
maxLength = Math.max(maxLength, cache[0][j]);
}
//general cases
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == '0') {
cache[i][j] = 0;
} else {
cache[i][j] = Math.min(Math.min(cache[i][j - 1], cache[i - 1][j]), cache[i - 1][j - 1]) + 1;
maxLength = Math.max(maxLength, cache[i][j]);
}
}
}
return maxLength * maxLength;
}
对空间的优化:
其实不需要 m * n 大小的。
只有 n 的空间就可以了,用2个长为 n 的数组。
存储前一行pre的信息和当前行cur的信息。(一行结束后,pre = cur, cur = 0 )
参考:
https://leetcode.com/discuss/38489/easy-solution-with-detailed-explanations-8ms-time-and-space