题目描述
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
示例 1:
1 | 输入: |
示例 2:
1 | 输入: |
进阶:
- 一个直接的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。
- 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
- 你能想出一个常数空间的解决方案吗?
题解
题目乍看比较简单,但是比较坑的地方在于原地修改,修改时需要记录原本是0的元素。
额外空间
空间复杂度 $O(M \times N)$
思路
- 遍历所有节点,如果
matrix[i][j]
为0
,则将所在行i
与列j
的所有元素置为0
。 - 记录一个二维数组
visited[][]
,表示这个节点是否访问过。 - 置
0
过程中,将访问数组visited[i][j]
记录为true
。如果原本值已经为0
,则记录为false
,以便下次可以扫描到。
复杂度
- 时间复杂度:$O((M \times N) \times (M+N))$
- 空间复杂度:$O(M \times N)$
代码
1 | // C++ |
空间复杂度 $O(M+N)$
思路
- 第一次遍历所有元素,使用
zeroRows[M]
和zeroCols[N]
来记录哪些行和列有0
元素存在。 - 第二次遍历根据记录,如果
zeroRows[i] == true || zeroCols[j] == true
,则将matrix[i][j]
置为0
。
复杂度
- 时间复杂度:$O(M \times N)$
- 空间复杂度:$O(M + N)$
代码
1 | // C++ |
暴力法 空间复杂度 $O(1)$
思路
- 第一次遍历,如果
matrix[i][j]
为0
,则修改所在行i
与列j
的所有元素,将所有非0
元素置为一个特殊值MODIFED = -1000000
,说明该位置的元素被修改过。 - 第二次遍历,如果
matrix[i][j] == MODIFIED
,则将其置为0
。
复杂度
- 时间复杂度:$O((M \times N) \times (M + N))$
- 空间复杂度:$O(1)$
代码
1 | // C++ |
改进方案 空间复杂度 $O(1)$
算法
- 遍历整个矩阵,将矩阵的第一行和第一列的所有元素做为标志位,代表这行或这列需要置为
0
。
1 | if matrix[i][j] == 0 { |
由于第一行与第一列被用作标志位,所以需要额外的变量标记第一行与第一列,
isCol
记录第一列是否需要置0
,matrix[0][0]
则用来标记第一行是否需要置0
。从第二行与第二列即
matrix[1][1]
开始遍历1
2
3if matrix[i][0] == 0 || matrix[i][1] == 0 {
matrix[i][j] = 0;
}如果
matrix[0][0] == 0
,则第一行置为0
。- 如果
isCol == true
,则第一列置为0
。
复杂度
- 时间复杂度:$O(M \times N)$
- 空间复杂度:$O(1)$
代码
1 | // C++ |
参考链接
- 73. Set Matrix Zeroes, LeetCode solution.