您现在的位置是:首页 >技术杂谈 >Leetcode 221. 最大正方形网站首页技术杂谈

Leetcode 221. 最大正方形

专注如一 2024-06-27 12:01:03
简介Leetcode 221. 最大正方形
  • Leetcode 221. 最大正方形
  • 题目
    • 在一个由 ‘0’ 和 ‘1’ 组成的二维矩阵内,找到只包含 ‘1’ 的最大正方形,并返回其面积。
    • m == matrix.length
    • n == matrix[i].length
    • 1 <= m, n <= 300
    • matrix[i][j] 为 ‘0’ 或 ‘1’
  • 解法
    • 动态规划+状态压缩:定义三个 dp,分别为:
      • rowDp[i][j]:在第 i 行当前节点(含)往前连续有多少个 1
      • colDp[i][j]:在第 j 列当前节点(含)往上连续有多少个 1
      • squareDp[i][j]:以当前节点为右下角,连续 1 的最大正方形边长
    • 此时循环矩阵,如果为 0 则全是 0,如果为 1 转移方程为:
      • rowDp[i][j] = rowDp[i][j - 1] + 1
      • colDp[i][j] = colDp[i - 1][j] + 1
      • squareDp[i][j] = min(rowDp[i][j], rowDp[i][j], squareDp[i - 1][j - 1] + 1) 意为左上的正方形加上当前行、当前列可以形成的最大正方形
    • 空间压缩:rowDp 压缩后每个值等于前一个值加一(矩阵为 1),colDp 压缩后每个值等于上一轮循环当前位加一(矩阵为 1),squareDp 必须使用二维数组,因为每次遍历时会将上一行的前一位数据更新掉,同时 squareDp[i][j] = min(rowDp[i][j](当前行列), rowDp[i][j](当前行列), squareDp[i - 1][j - 1] + 1(上一行、上一列))
    • 时间复杂度:O(m*n),空间复杂度:O(n)
  • 代码
    /**
     * 动态规划+状态压缩:定义三个 dp,分别为:
     *     rowDp[i][j]:在第 i 行当前节点(含)往前连续有多少个 1
     *     colDp[i][j]:在第 j 列当前节点(含)往上连续有多少个 1
     *     squareDp[i][j]:以当前节点为右下角,连续 1 的最大正方形边长
     * 此时循环矩阵,如果为 0 则全是 0,如果为 1 转移方程为:rowDp[i][j] = rowDp[i][j - 1] + 1,colDp[i][j] = colDp[i - 1][j] + 1,
     * squareDp[i][j] = min(rowDp[i][j], rowDp[i][j], squareDp[i - 1][j - 1] + 1) 意为左上的正方形加上当前行、当前列可以形成的最大正方形
     * 空间压缩:rowDp 压缩后每个值等于前一个值加一(矩阵为 1),colDp 压缩后每个值等于上一轮循环当前位加一(矩阵为 1),
     * squareDp 必须使用二维数组,因为每次遍历时会将上一行的前一位数据更新掉,
     * 同时 squareDp[i][j] = min(rowDp[i][j](当前行列), rowDp[i][j](当前行列), squareDp[i - 1][j - 1] + 1(上一行、上一列))
     * 时间复杂度:O(m*n),空间复杂度:O(n)
     */
    public int solution(char[][] matrix) {
        // 判空
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return 0;
        }
        int m = matrix.length;
        int n = matrix[0].length;
        // 定义三个 dp,空间压缩,避免判断下标 0 可以让 dp 往后/下移动一位
        int[] rowDp = new int[n + 1];
        int[] colDp = new int[n + 1];
        // 注意必须使用二维数组,因为顺序遍历时会将上一行的前一位数据更新
        int[][] squareDp = new int[2][n + 1];
        // 循环处理三个 dp
        int res = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == '0') {
                    rowDp[j + 1] = 0;
                    colDp[j + 1] = 0;
                    squareDp[i & 1][j + 1] = 0;
                } else {
                    rowDp[j + 1] = rowDp[j] + 1;
                    colDp[j + 1] = colDp[j + 1] + 1;
                    // squareDp[i][j] = min(rowDp[i][j](当前行列), rowDp[i][j](当前行列), squareDp[i - 1][j - 1] + 1(上一行、上一列))
                    squareDp[i & 1][j + 1] = Math.min(rowDp[j + 1], Math.min(colDp[j + 1], squareDp[(i + 1) & 1][j] + 1));
                    res = Math.max(res, squareDp[i & 1][j + 1]);
                }
//                System.out.print(matrix[i][j] + " : " + rowDp[j + 1] + " : " + colDp[j + 1] + " : " + squareDp[i & 1][j + 1] + "	");
            }
//            System.out.println();
        }
        return res * res;
    }
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。