Leetcode221.最大正方形——理解动态规划递归式(状态转移方程)

引入

这道题221.最大正方形是这样的:

在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。
示例:
输入:
1 0 1 0 0
1 0 1 1 1
1 1 1 1 1
1 0 0 1 0
输出: 4

很明显是用动态规划来解,但是动态规划的方程不容易找到。

221.最大正方形 题解

理解 min(上, 左, 左上) + 1
如题,该题涉及到下列形式的代码:

if (grid(i, j) == 1) {
    dp(i, j) = min(dp(i-1, j), dp(i, j-1), dp(i-1, j-1)) + 1;
}

翻译成中文:
若某格子值为 1 ,则以此为右下角的正方形的、最大边长为:上面的正方形、左面的正方形或左上的正方形中,最小的那个,再加上此格。

先来阐述简单共识:

  • 若形成正方形(非单 1),以当前为右下角的视角看,则需要:当前格、上、左、左上都是 1
  • 可以换个角度:当前格、上、左、左上都不能受 0 的限制,才能成为正方形

直接上图更容易理解
在这里插入图片描述
也就是取3个(左上、左边、上边)正方形的边长的交集,就像木桶短板理论一样。

所以本题代码如下:

public int maximalSquare(char[][] matrix) {
    // base condition
    if (matrix == null || matrix.length < 1 || matrix[0].length < 1) return 0;

    int height = matrix.length;
    int width = matrix[0].length;
    int maxSide = 0;

    // 相当于已经预处理新增第一行、第一列均为0
    int[][] dp = new int[height + 1][width + 1];

    for (int row = 0; row < height; row++) {
        for (int col = 0; col < width; col++) {
            if (matrix[row][col] == '1') {
                dp[row + 1][col + 1] = Math.min(Math.min(dp[row + 1][col], dp[row][col + 1]), dp[row][col]) + 1;
                maxSide = Math.max(maxSide, dp[row + 1][col + 1]);
            }
        }
    }
    return maxSide * maxSide;
}

同理可知,题目:1277. 统计全为 1 的正方形子矩阵,仍然使用相同的思路。
代码如下:

class Solution {
    public int countSquares(int[][] matrix) {
        if (matrix==null||matrix.length==0||matrix[0].length==0) return 0;
        int row=matrix.length;
        int col=matrix[0].length;
        int count=0;
        int[][] dp=new int[row+1][col+1];
        for(int i=0;i<row;i++){
            for(int j=0;j<col;j++){
                if(matrix[i][j]==1){
                    dp[i+1][j+1]=Math.min(Math.min(dp[i+1][j],dp[i][j+1]),dp[i][j])+1;
                    count+=dp[i+1][j+1];
                }
            }
        }
        return count;
    }
}

这里使用count+=dp[i+1][j+1];,可以思考下为什么这样算是正确的?

比如输入:matrix =
[
[0,1,1,1],
[1,1,1,1],
[0,1,1,1]
]

我们新加入右下角的1,那么新增了多少个正方形呢?3个,刚好是dp的边长。

发布了392 篇原创文章 · 获赞 326 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/No_Game_No_Life_/article/details/104513780