矩阵置零问题的巧妙解法:为何第一反应想到的解法很有可能是坑?
2023-10-24 10:16:51
解开矩阵置零难题:为何直接归零行不通?
当你初次接触 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]]
常见问题解答
-
为什么我们需要使用额外的数组来记录需要归零的行和列?
直接归零可能会导致无法区分原本就为 0 的元素和因为其他 0 元素而被归零的元素。额外的数组可以让我们明确哪些元素需要被归零。
-
这种方法的时间复杂度是多少?
O(m×n),其中 m 和 n 分别是矩阵的行数和列数。
-
为什么空间复杂度是 O(m+n)?
两个额外的数组分别记录了需要归零的行和列,因此空间复杂度为 O(m+n)。
-
能否使用更优化的算法解决这个问题?
可以使用原地算法,它不需要额外的空间复杂度。然而,它的实现可能更加复杂。
-
这种方法可以用来解决其他类似的问题吗?
是的,这种方法可以用来解决类似的问题,例如矩阵置一问题或稀疏矩阵求和问题。