返回

矩阵置零问题的巧妙解法:为何第一反应想到的解法很有可能是坑?

人工智能

解开矩阵置零难题:为何直接归零行不通?

当你初次接触 LeetCode 第 73 题矩阵置零问题时,直觉往往会告诉你将所有元素归零。然而,这种看似简单的解决方式却暗藏着陷阱,可能导致错误的结果。

为何直接归零会出错?

LeetCode 73 题要求我们处理一个包含 0 和 1 的矩阵。当遇到一个 0 元素时,我们需要将它所在的行和列的所有元素也归零。但如果我们直接将所有元素归零,就无法区分哪些元素原本就是 0,哪些元素是因为其他 0 元素而被归零的。

举个例子,假设我们有一个 2x2 矩阵:

[[1, 1],
 [0, 1]]

按照直接归零的方法,我们将得到:

[[0, 0],
 [0, 0]]

然而,正确的答案应该是:

[[1, 0],
 [0, 0]]

因为矩阵中只有左下角元素为 0,它所在的行和列应该归零,而其他元素应该保持不变。

巧妙的解决方式

为了正确解决这个问题,我们需要采用一种更巧妙的方式。我们可以使用两个额外的数组来记录需要归零的行和列。当遇到一个 0 元素时,我们将它所在的行和列的标志位置为 1。然后,遍历整个矩阵,将所有标志位为 1 的行和列的所有元素都归零。

这种方法的时间复杂度为 O(m×n),空间复杂度为 O(m+n),其中 m 和 n 分别是矩阵的行数和列数。

代码示例

以下 Python 代码演示了这种解决方式:

def set_zeros(matrix):
    """
    将矩阵中包含 0 的元素所在的行和列都归零.

    参数:
        matrix: 输入矩阵

    返回:
        无
    """

    # 创建两个额外的数组来记录需要归零的行和列
    row_flags = [False] * len(matrix)
    col_flags = [False] * len(matrix[0])

    # 遍历矩阵,找到需要归零的行和列
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            if matrix[i][j] == 0:
                row_flags[i] = True
                col_flags[j] = True

    # 将所有需要归零的行和列中的所有元素都归零
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            if row_flags[i] or col_flags[j]:
                matrix[i][j] = 0

    return matrix


# 测试代码
matrix = [[1, 1, 1],
          [1, 0, 1],
          [1, 1, 1]]

set_zeros(matrix)

print(matrix)

运行结果:

[[1, 0, 1],
 [0, 0, 0],
 [1, 0, 1]]

常见问题解答

  1. 为什么我们需要使用额外的数组来记录需要归零的行和列?

    直接归零可能会导致无法区分原本就为 0 的元素和因为其他 0 元素而被归零的元素。额外的数组可以让我们明确哪些元素需要被归零。

  2. 这种方法的时间复杂度是多少?

    O(m×n),其中 m 和 n 分别是矩阵的行数和列数。

  3. 为什么空间复杂度是 O(m+n)?

    两个额外的数组分别记录了需要归零的行和列,因此空间复杂度为 O(m+n)。

  4. 能否使用更优化的算法解决这个问题?

    可以使用原地算法,它不需要额外的空间复杂度。然而,它的实现可能更加复杂。

  5. 这种方法可以用来解决其他类似的问题吗?

    是的,这种方法可以用来解决类似的问题,例如矩阵置一问题或稀疏矩阵求和问题。