LeetCode 221. 最大正方形

173 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第25天,点击查看活动详情.

221. 最大正方形

题目描述

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

解题思路

思路一: 暴力法

我们应该找到最大正方形的边长, 暴力法具体做法如下:

  • 遍历矩阵中的每个元素,每次遇到 1,则将该元素作为正方形的左上角;

  • 确定正方形的左上角后,根据左上角所在的行和列计算可能的最大正方形的边长(正方形的范围不能超出矩阵的行数和列数),在该边长范围内寻找只包含 1 的最大正方形;

  • 每次在下方新增一行以及在右方新增一列,判断新增的行和列是否满足所有元素都是 1

实现代码如下:

/**
 * @param {character[][]} matrix
 * @return {number}
 */
var maximalSquare = function(matrix) {
    let maxSide = 0;
    let rows = matrix.length, columns = matrix[0].length;
    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < columns; j++) {
            if (matrix[i][j] == '1') {
                // 遇到一个 1 作为正方形的左上角
                maxSide = Math.max(maxSide, 1);
                // 计算可能的最大正方形边长
                let currentMaxSide = Math.min(rows - i, columns - j);
                for (let k = 1; k < currentMaxSide; k++) {
                    // 判断新增的一行一列是否均为 1
                    let flag = true;
                    if (matrix[i + k][j + k] == '0') {
                        break;
                    }
                    for (let m = 0; m < k; m++) {
                    	// 判断左下 右上
                        if (matrix[i + k][j + m] == '0' || matrix[i + m][j + k] == '0') {
                            flag = false;
                            break;
                        }
                    }
                    if (flag) {
                        maxSide = Math.max(maxSide, k + 1);
                    } else {
                        break;
                    }
                }
            }
        }
    }
    let maxSquare = maxSide * maxSide;
    return maxSquare; 
};
  • 时间复杂度: O(mnmin(m,n)2)O(mn * min(m, n)^2), 其中m和n是矩阵的行数和列数;

    • 遍历矩阵的时间复杂度是O(mn);
    • 遍历正方形复杂度是O(min(m,n)2)O(min(m, n)^2), 因为正方形其边长不能超过m和n中的最小值;
  • 空间复杂度: O(1)

思路二:动态规划

1. 状态定义
dp[i][j]表示以 (i, j) 为右下角,且只包含 1 的正方形的边长最大值;

2. 确定递推公式
对于每个位置 (i, j),检查在矩阵中该位置的值:

  • 如果该位置的值是 0,则dp[i][j]=0,因为当前位置不可能在由 1 组成的正方形中;

  • 如果该位置的值是 1,则dp[i][j] 的值由其上方、左方和左上方的三个相邻位置的 dp 值决定。具体而言,当前位置的元素值等于三个相邻位置的元素中的最小值加 1,状态转移方程如下:

dp[i][j]=min(dp[i1][j],dp[i1][j1],dp[i][j1])+1dp[i][ j]=min(dp[i−1][j], dp[i−1][ j−1], dp[i][ j−1])+1

3. 初始状态
如果 i 和 j 中至少有一个为 00,则以位置 (i, j) 为右下角的最大正方形的边长只能是 1,因此 dp[i][j]=1

实现代码如下:

/**
 * @param {character[][]} matrix
 * @return {number}
 */
var maximalSquare = function(matrix) {
    let maxSide = 0,
        rows = matrix.length, 
        columns = matrix[0].length,
        dp = Array.from(Array(rows), () => Array(columns).fill(0));
    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < columns; j++) {
            if (matrix[i][j] == '1') {
                if (i == 0 || j == 0) {
                    dp[i][j] = 1;
                } else {
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                }
                maxSide = Math.max(maxSide, dp[i][j]);
            }
        }
    }
    return maxSide * maxSide; 
};
  • 时间复杂度:O(mn),其中 m 和 n 是矩阵的行数和列数;

  • 空间复杂度:O(mn);

参考资料

leetcode.cn/problems/ma…