对Leetcode 221. Maximal Square 题目的求解。
Problem Description
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
Analysis
看到网格类题目,首先想到动态规划。既然要用动态规划,我们必须要找到递归规律。我们很自然的想到,用dp[i][j]表示以(i,j)为右下角的最大的正方形。那么
- 如果matrix[i][j]为0,则dp[i][j]必为0
- 如果matrix[i][j]为1,则有两种情况
- dp[i-1][j-1] > max(dp[i-1][j], dp[i][j-1]) 这种情况下,我们最大能得到min(dp[i-1][j], dp[i][j-1])+1的正方形。
- dp[i-1][j-1] < max(dp[i-1][j], dp[i][j-1]) 这种情况下,我们最大能得到dp[i-1][j-1]+1的正方形。
所以dp[i][j] = Math.min(Math.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
Solution 1
public static int maximalSquare(char[][] matrix) {
//right down corner
if (matrix.length < 1 || matrix[0].length < 1) return 0;
int dp[][] = new int[matrix.length + 1][matrix[0].length + 1];
int max = 0;
for (int i = 1; i < dp.length; ++i){
for (int j = 1; j < dp[i].length; ++j){
if (matrix[i-1][j-1] == '0') dp[i][j] = 0;
else dp[i][j] = Math.min(Math.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
max = Math.max(dp[i][j], max);
}
}
return max*max;
}
Solution 2
事实上,我们并不需要mxn的矩阵来储存所有的dp元素,2xn的矩阵即可,由此我们可以将空间复杂度降低至O(n),达到理论上最优。
public static int maximalSquare(char[][] matrix) {
//right down corner
if (matrix.length < 1 || matrix[0].length < 1) return 0;
int dp[][] = new int[2][matrix[0].length + 1];
int max = 0;
for (int i = 1; i < matrix.length + 1; ++i){
for (int j = 1; j < matrix[0].length + 1; ++j){
int cur = (i-1) % 2;
int prev = i % 2;
if (matrix[i-1][j-1] == '0') dp[cur][j] = 0;
else dp[cur][j] = Math.min(Math.min(dp[prev][j], dp[cur][j-1]), dp[prev][j-1]) + 1;
max = Math.max(dp[cur][j], max);
}
}
return max*max;
}
Solution 3
那么,时间复杂度还有没有优化的空间呢?好像没有了,但是我的代码只能击败5%的人,为什么呢?