leetcode-最大正方形

111 阅读2分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

一天都在开车路上,稍微下点雨,路上就堵得不行了。回到家继续刷leetcode。

题目

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

示例 1:
max1grid.jpg 输入: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]]
输出: 4

示例 2:
max2grid.jpg 输入: matrix = [["0","1"],["1","0"]]
输出: 1

示例 3:
输入: matrix = [["0"]]
输出: 0

思路

这题想了很多,自己没想出来。看了官方题解,发现挺有意思的,记录一下。
定义二维数据dp[i][j],代表以i、j位置的单元格作为正方形右下角的最大正方形边长,给出的状态转移方程是

dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1
这个状态转移方程有点难想明白,证明过程如下:

题解1.png 如上图1所示,如果存在dp[i][j] = 4,那么必然存在

  • dp[i-1][j] >= 3
  • dp[i][j-1] >= 3
  • dp[i-1][j-1] >= 3 综合起来,就是

min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) >= dp[i][j] - 1

题解2.png

又如上图2所示,如果存在 dp[i-1][j] >= 3 && dp[i][j-1] >= 3 && dp[i-1][j-1] >= 3 那么必然可以得到,dp[i][j] >= 4,即

dp[i][j] >= min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1 联立上面的2个不等式 dp[i][j] <= min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1 dp[i][j] >= min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1

所以可以得到:

dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1

Java版本代码

class Solution {
    public int maximalSquare(char[][] matrix) {
        int max = 0;
        int rows = matrix.length;
        int cols = matrix[0].length;
        int[][] dp = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (i == 0 || j == 0) {
                    if (matrix[i][j] == '1') {
                        dp[i][j] = 1;
                    } else {
                        dp[i][j] = 0;
                    }
                } else {
                    if (matrix[i][j] == '1') {
                        dp[i][j] = Integer.min(Integer.min(dp[i-1][j], dp[i][j-1]), dp[i-1][j-1]) + 1;
                    } else {
                        dp[i][j] = 0;
                    }
                }
                if (dp[i][j] > max) {
                    max = dp[i][j];
                }
            }
        }
        return max * max;
    }
}