leetcode 221. Maximal Square 最大正方形面积 + 动态规划DP实现

淩亂°似流年 2022-06-08 11:55 289阅读 0赞

Given a 2D binary matrix filled with 0’s and 1’s, find the largest square containing only 1’s and return its area.

For example, given the following matrix:

1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
Return 4.

原以为是DFS深度优先遍历,后来一想,这个是求最大的正方形的面积,DFS似乎解决不了问题。后来我一直想着使用DFS解决问题,但是想不出来,后来网上看到了一个DP做法,这个方法十分的棒。

这个一个很基本的动态规划DP的做法,必须要会做

主要思路如下:当我们判断以某个点为正方形右下角时最大的正方形时,那它的上方,左方和左上方三个点也一定是某个正方形的右下角,否则该点为右下角的正方形最大就是它自己了。这是定性的判断,那具体的最大正方形边长呢?我们知道,该点为右下角的正方形的最大边长,最多比它的上方,左方和左上方为右下角的正方形的边长多1,最好的情况是是它的上方,左方和左上方为右下角的正方形的大小都一样的,这样加上该点就可以构成一个更大的正方形。

但如果它的上方,左方和左上方为右下角的正方形的大小不一样,合起来就会缺了某个角落,这时候只能取那三个正方形中最小的正方形的边长加1了。

s假设dpi表示以i,j为右下角的正方形的最大边长,则有

dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
dp[i][j]表示已(i,j)为右下角的正方形的最大的边长

代码如下:

  1. /*
  2. * 当我们判断以某个点为正方形右下角时最大的正方形时,那它的上方,左方和左上方三个点也一定
  3. * 是某个正方形的右下角,否则该点为右下角的正方形最大就是它自己了。这是定性的判断,
  4. * 那具体的最大正方形边长呢?我们知道,该点为右下角的正方形的最大边长,最多比它的上方,
  5. * 左方和左上方为右下角的正方形的边长多1,最好的情况是是它的上方,左方和左上方为右下角的
  6. * 正方形的大小都一样的,这样加上该点就可以构成一个更大的正方形。
  7. *
  8. * 但如果它的上方,左方和左上方为右下角的正方形的大小不一样,合起来就会缺了某个角落,
  9. * 这时候只能取那三个正方形中最小的正方形的边长加1了。
  10. * s假设dpi表示以i,j为右下角的正方形的最大边长,则有
  11. * dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
  12. *
  13. * dp[i][j]表示已(i,j)为右下角的正方形的最大的边长
  14. *
  15. * */
  16. public class Solution
  17. {
  18. public int maximalSquare(char[][] matrix)
  19. {
  20. if(matrix==null || matrix.length<=0)
  21. return 0;
  22. int [][]dp=new int[matrix.length][matrix[0].length];
  23. //注意res的初始化
  24. int res=0;
  25. for(int i=0;i<matrix.length;i++)
  26. {
  27. if(matrix[i][0]=='1')
  28. {
  29. dp[i][0]=1;
  30. res=1;
  31. }else
  32. dp[i][0]=0;
  33. }
  34. for(int i=0;i<matrix[0].length;i++)
  35. {
  36. if(matrix[0][i]=='1')
  37. {
  38. dp[0][i]=1;
  39. res=1;
  40. }else
  41. dp[0][i]=0;
  42. }
  43. for(int i=1;i<matrix.length;i++)
  44. {
  45. for(int j=1;j<matrix[0].length;j++)
  46. {
  47. if(matrix[i][j]=='0')
  48. dp[i][j]=0;
  49. else
  50. {
  51. dp[i][j] = Math.min(dp[i-1][j-1], Math.min(dp[i-1][j],dp[i][j-1])) + 1;
  52. res = Math.max(res, dp[i][j]);
  53. }
  54. }
  55. }
  56. //因为res是最大边长,所以边长的平方就是面积
  57. return res*res;
  58. }
  59. }

下面是C++的做法,就是一个简单的DP,很棒的做法

代码如下:

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <set>
  5. #include <map>
  6. using namespace std;
  7. class Solution
  8. {
  9. public:
  10. int maximalSquare(vector<vector<char>>& mat)
  11. {
  12. if (mat.size() <= 0)
  13. return 0;
  14. int res = 0;
  15. vector<vector<int>> dp(mat.size(), vector<int>(mat[0].size(), 0));
  16. for (int i = 0; i < mat.size(); i++)
  17. {
  18. if (mat[i][0] == '1')
  19. {
  20. dp[i][0] = 1;
  21. res = 1;
  22. }
  23. else
  24. dp[i][0] = 0;
  25. }
  26. for (int i = 0; i < mat[0].size(); i++)
  27. {
  28. if (mat[0][i] == '1')
  29. {
  30. dp[0][i] = 1;
  31. res = 1;
  32. }
  33. else
  34. dp[0][i] = 0;
  35. }
  36. for (int i = 1; i < mat.size(); i++)
  37. {
  38. for (int j = 1; j < mat[0].size(); j++)
  39. {
  40. if (mat[i][j] == '1')
  41. {
  42. dp[i][j] = min(dp[i - 1][j], min(dp[i - 1][j - 1], dp[i][j - 1])) + 1;
  43. res = max(res, dp[i][j]);
  44. }
  45. else
  46. dp[i][j] = 0;
  47. }
  48. }
  49. return res*res;
  50. }
  51. };

发表评论

表情:
评论列表 (有 0 条评论,289人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Leetcode 221 正方形(DP)

    题目重述 在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。 示例 1: ![在这里插入图片描述][watermark