题目

image.png

思路

  • 思路一:暴力递归
  • 思路二:备忘录
  • 思路三:动态规划
  • 思路四:优化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. //1.暴力递归
  2. int max = 0;
  3. public int maximalSquare(char[][] matrix) {
  4. recur(matrix, matrix.length - 1, matrix[0].length - 1);
  5. return max * max;
  6. }
  7. public int recur(char[][] matrix, int i, int j) {
  8. if (i < 0 || j < 0) return 0;
  9. int val = matrix[i][j] - '0';
  10. int res = Math.min(
  11. Math.min(recur(matrix, i - 1, j), recur(matrix, i, j - 1)),
  12. recur(matrix, i - 1, j - 1)) + val;
  13. max = Math.max(res, max);
  14. return val == 0 ? 0 : res;
  15. }
  16. //2.备忘录
  17. int max = 0;
  18. int[][] dp;
  19. public int maximalSquare(char[][] matrix) {
  20. dp = new int[matrix.length][matrix[0].length];
  21. for (int i = 0; i < matrix.length; i++) {
  22. for (int j = 0; j < matrix[0].length; j++) {
  23. dp[i][j] = -1;
  24. }
  25. }
  26. recur(matrix, matrix.length - 1, matrix[0].length - 1);
  27. return max * max;
  28. }
  29. public int recur(char[][] matrix, int i, int j) {
  30. if (i < 0 || j < 0) return 0;
  31. if (dp[i][j] != -1) return dp[i][j];
  32. int val = matrix[i][j] - '0';
  33. int res = Math.min(
  34. Math.min(recur(matrix, i - 1, j), recur(matrix, i, j - 1)),
  35. recur(matrix, i - 1, j - 1)) + val;
  36. max = Math.max(res, max);
  37. dp[i][j] = val == 0 ? 0 : res;
  38. return dp[i][j];
  39. }
  40. //3.动态规划
  41. public int maximalSquare(char[][] matrix) {
  42. if (matrix.length == 0 || matrix[0].length == 0) return 0;
  43. int res = 0;
  44. int[][] dp = new int[matrix.length][matrix[0].length];
  45. for (int i = 0; i < matrix.length; i++) {
  46. dp[i][0] = matrix[i][0] - '0';
  47. res = Math.max(res, dp[i][0]);
  48. }
  49. for (int j = 0; j < matrix[0].length; j++) {
  50. dp[0][j] = matrix[0][j] - '0';
  51. res = Math.max(res, dp[0][j]);
  52. }
  53. for (int i = 1; i < matrix.length; i++) {
  54. for (int j = 1; j < matrix[0].length; j++) {
  55. dp[i][j] = matrix[i][j] - '0';
  56. if (dp[i][j] == 1) {
  57. dp[i][j] = Math.min(
  58. Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
  59. res = Math.max(res, dp[i][j]);
  60. }
  61. }
  62. }
  63. return res * res;
  64. }
  65. //后面觉得不用开辟数组,效率会高一点,结果一样是7ms,反而花费空间更多
  66. public int maximalSquare(char[][] matrix) {
  67. if (matrix.length == 0 || matrix[0].length == 0) return 0;
  68. char res = '0';
  69. for (int i = 0; i < matrix.length; i++) {
  70. for (int j = 0; j < matrix[0].length; j++) {
  71. if (i > 0 && j > 0 && matrix[i][j] == '1') {
  72. matrix[i][j] = (char)
  73. (min(min(matrix[i - 1][j], matrix[i][j - 1]), matrix[i - 1][j - 1]) + 1);
  74. }
  75. res = max(res, matrix[i][j]);
  76. }
  77. }
  78. return (res - '0') * (res - '0');
  79. }
  80. public char min(char c1, char c2) {
  81. if (c1 < c2) return c1;
  82. return c2;
  83. }
  84. public char max(char c1, char c2) {
  85. if (c1 > c2) return c1;
  86. return c2;
  87. }
  88. //后面觉得直接把初始化条件放在里面去,好一点,7ms
  89. public int maximalSquare(char[][] matrix) {
  90. if (matrix.length == 0 || matrix[0].length == 0) return 0;
  91. int res = 0;
  92. int[][] dp = new int[matrix.length][matrix[0].length];
  93. for (int i = 0; i < matrix.length; i++) {
  94. for (int j = 0; j < matrix[0].length; j++) {
  95. dp[i][j] = matrix[i][j] - '0';
  96. if (i > 0 && j > 0 && dp[i][j] == 1) {
  97. dp[i][j] = Math.min(
  98. Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
  99. }
  100. res = Math.max(res, dp[i][j]);
  101. }
  102. }
  103. return res * res;
  104. }
  105. //再下一步就是优化dp数组,由于只用到三个元素可以压缩为一维,6ms
  106. public int maximalSquare(char[][] matrix) {
  107. if (matrix.length == 0 || matrix[0].length == 0) return 0;
  108. int res = 0, prev = 0, len = matrix[0].length;;
  109. int[] dp = new int[len];
  110. for (int i = 0; i < matrix.length; i++) {
  111. for (int j = 0; j < matrix[0].length; j++) {
  112. int t = dp[j];
  113. dp[j] = matrix[i][j] - '0';
  114. if (i > 0 && j > 0 && dp[j] == 1) {
  115. dp[j] = Math.min(Math.min(t, dp[j - 1]), prev) + 1;
  116. }
  117. prev = t;
  118. res = Math.max(dp[j], res);
  119. }
  120. }
  121. return res * res;
  122. }
  123. //后来看到别人写的更好初始值处理的动态规划,7ms
  124. public int maximalSquare(char[][] matrix) {
  125. if (matrix.length == 0 || matrix[0].length == 0) return 0;
  126. int res = 0, m = matrix.length, n = matrix[0].length;
  127. int[][] dp = new int[m + 1][n + 1];
  128. for (int i = 1; i <= m; i++) {
  129. for (int j = 1; j <= n; j++) {
  130. if (matrix[i - 1][j - 1] == '1') {
  131. dp[i][j] = Math.min(
  132. Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
  133. res = Math.max(res, dp[i][j]);
  134. }
  135. }
  136. }
  137. return res * res;
  138. }
  139. //我再把它压缩为一维数组,5ms
  140. public int maximalSquare(char[][] matrix) {
  141. if (matrix.length == 0 || matrix[0].length == 0) return 0;
  142. int res = 0, prev = 0, len = matrix[0].length;;
  143. int[] dp = new int[len + 1];
  144. for (int i = 1; i <= matrix.length; i++) {
  145. for (int j = 1; j <= matrix[0].length; j++) {
  146. int t = dp[j];
  147. if (matrix[i - 1][j - 1] == '1') {
  148. dp[j] = Math.min(Math.min(t, dp[j - 1]), prev) + 1;
  149. res = Math.max(dp[j], res);
  150. } else {
  151. dp[j] = 0;
  152. }
  153. prev = t;
  154. }
  155. }
  156. return res * res;
  157. }

最大正方形