📌  相关文章
📜  从源单元格到二进制矩阵的目标单元格通过仅由 1 组成的单元格的最短路径(1)

📅  最后修改于: 2023-12-03 15:36:19.392000             🧑  作者: Mango

从源单元格到二进制矩阵的目标单元格通过仅由 1 组成的单元格的最短路径

介绍

在二进制矩阵中,我们给出了一些 0 和 1 元素,请你编写一个程序,找到由 1 组成的最大正方形,并返回该正方形的面积。

本题中,我们定义大正方形为边长大于等于 2 的正方形,而不是边长恰好为 2 的正方形。

这道题可以用动态规划求解,通过建立状态转移方程来解决。而状态转移方程的构建则需要对问题进行拆分,设定边界值以及数组初始值等。

解法
状态定义

设 $dp(i,j)$ 为以 $(i,j)$ 为右下角的最大正方形面积。其中,$(i,j)$ 为矩阵中的二维坐标。注意此处状态定义与传统的二维动态规划不同,这是因为仅考虑以该点为右下角的最大正方形面积,可以方便地对从小到大遍历矩阵的每一个元素。

边界值

对于边界元素,显然 $dp(i,0)$ 或 $dp(0,j)$ 都应该为 $matrix(i,0)$ 或 $matrix(0,j)$,即矩阵中的元素本身。这是因为边界上的元素无论如何都无法构成正方形。

状态转移方程

对于任意 $(i,j)$ 元素,如果其为1,则以其为右下角的最大正方形的边长应为 $1+min(dp(i-1,j),dp(i,j-1),dp(i-1,j-1))$,这里的 $dp(i-1,j),dp(i,j-1),dp(i-1,j-1)$ 分别对应以 $(i,j)$ 的上、左、左上三个方向的元素为右下角的最大正方形的边长。同时,无论如何 $dp(i,j)$ 都应该不小于1。

具体而言,$dp(i,j)$ 取决于以其上、左、左上三个方向的元素为右下角的最大正方形的边长,它们的最小值加上1即为以 $(i,j)$ 为右下角的最大正方形的边长。如果 $(i,j)$ 本身的元素值为0,则以其为右下角的最大正方形的边长显然为0。

状态转移方程为

$$ dp(i,j) = \begin{cases} 0, &matrix_{i,j}=0 \ 1+\min(dp(i-1,j), dp(i,j-1),dp(i-1,j-1)),&matrix_{i,j}=1 \ \end{cases} $$

初始化

对于数组 $dp$ 中的所有元素,都应设为0。这是因为如果一个 $(i,j)$ 元素本身的值为0,则以其为右下角的最大正方形的边长也一定为0,应当初始化为0。同时,这也为状态转移方程提供了正确的边界条件。

时间复杂度和空间复杂度

时间复杂度:$O(mn)$,其中 $m$ 和 $n$ 分别表示矩阵的行数和列数。

空间复杂度:$O(mn)$,需要额外开辟一个 $mn$ 的数组 $dp$。

代码
def maximalSquare(matrix) -> int:
    if not matrix:
        return 0
    m, n = len(matrix), len(matrix[0])
    dp = [[0] * (n + 1) for _ in range(m + 1)]
    max_len = 0
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if matrix[i - 1][j - 1] == '1':
                dp[i][j] = 1 + min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1])
                max_len = max(max_len, dp[i][j])
    return max_len ** 2