题目
思路
- 思路一:暴力递归
- 思路二:备忘录
- 思路三:动态规划
- 思路四:优化dp数组动态规划
- 动态规划:dp[i][j]表示dp[i][j]包含在内所能表示的最大正方形边长,通过观察我们可以得知dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], Math.min(dp[i - 1][j - 1])
代码
//1.暴力递归 int max = 0; public int maximalSquare(char[][] matrix) { recur(matrix, matrix.length - 1, matrix[0].length - 1); return max * max; } public int recur(char[][] matrix, int i, int j) { if (i < 0 || j < 0) return 0; int val = matrix[i][j] - '0'; int res = Math.min( Math.min(recur(matrix, i - 1, j), recur(matrix, i, j - 1)), recur(matrix, i - 1, j - 1)) + val; max = Math.max(res, max); return val == 0 ? 0 : res; } //2.备忘录 int max = 0; int[][] dp; public int maximalSquare(char[][] matrix) { dp = new int[matrix.length][matrix[0].length]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { dp[i][j] = -1; } } recur(matrix, matrix.length - 1, matrix[0].length - 1); return max * max; } public int recur(char[][] matrix, int i, int j) { if (i < 0 || j < 0) return 0; if (dp[i][j] != -1) return dp[i][j]; int val = matrix[i][j] - '0'; int res = Math.min( Math.min(recur(matrix, i - 1, j), recur(matrix, i, j - 1)), recur(matrix, i - 1, j - 1)) + val; max = Math.max(res, max); dp[i][j] = val == 0 ? 0 : res; return dp[i][j]; } //3.动态规划 public int maximalSquare(char[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return 0; int res = 0; int[][] dp = new int[matrix.length][matrix[0].length]; for (int i = 0; i < matrix.length; i++) { dp[i][0] = matrix[i][0] - '0'; res = Math.max(res, dp[i][0]); } for (int j = 0; j < matrix[0].length; j++) { dp[0][j] = matrix[0][j] - '0'; res = Math.max(res, dp[0][j]); } for (int i = 1; i < matrix.length; i++) { for (int j = 1; j < matrix[0].length; j++) { dp[i][j] = matrix[i][j] - '0'; if (dp[i][j] == 1) { dp[i][j] = Math.min( Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1; res = Math.max(res, dp[i][j]); } } } return res * res; } //后面觉得不用开辟数组,效率会高一点,结果一样是7ms,反而花费空间更多 public int maximalSquare(char[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return 0; char res = '0'; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { if (i > 0 && j > 0 && matrix[i][j] == '1') { matrix[i][j] = (char) (min(min(matrix[i - 1][j], matrix[i][j - 1]), matrix[i - 1][j - 1]) + 1); } res = max(res, matrix[i][j]); } } return (res - '0') * (res - '0'); } public char min(char c1, char c2) { if (c1 < c2) return c1; return c2; } public char max(char c1, char c2) { if (c1 > c2) return c1; return c2; } //后面觉得直接把初始化条件放在里面去,好一点,7ms public int maximalSquare(char[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return 0; int res = 0; int[][] dp = new int[matrix.length][matrix[0].length]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { dp[i][j] = matrix[i][j] - '0'; if (i > 0 && j > 0 && dp[i][j] == 1) { dp[i][j] = Math.min( Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1; } res = Math.max(res, dp[i][j]); } } return res * res; } //再下一步就是优化dp数组,由于只用到三个元素可以压缩为一维,6ms public int maximalSquare(char[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return 0; int res = 0, prev = 0, len = matrix[0].length;; int[] dp = new int[len]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { int t = dp[j]; dp[j] = matrix[i][j] - '0'; if (i > 0 && j > 0 && dp[j] == 1) { dp[j] = Math.min(Math.min(t, dp[j - 1]), prev) + 1; } prev = t; res = Math.max(dp[j], res); } } return res * res; } //后来看到别人写的更好初始值处理的动态规划,7ms public int maximalSquare(char[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return 0; int res = 0, m = matrix.length, n = matrix[0].length; int[][] dp = new int[m + 1][n + 1]; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (matrix[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; res = Math.max(res, dp[i][j]); } } } return res * res; } //我再把它压缩为一维数组,5ms public int maximalSquare(char[][] matrix) { if (matrix.length == 0 || matrix[0].length == 0) return 0; int res = 0, prev = 0, len = matrix[0].length;; int[] dp = new int[len + 1]; for (int i = 1; i <= matrix.length; i++) { for (int j = 1; j <= matrix[0].length; j++) { int t = dp[j]; if (matrix[i - 1][j - 1] == '1') { dp[j] = Math.min(Math.min(t, dp[j - 1]), prev) + 1; res = Math.max(dp[j], res); } else { dp[j] = 0; } prev = t; } } return res * res; }
最大正方形