解法一:暴力法
首先想到的思路就是,遍历一遍这个二维矩阵,然后把所有0所在的行和列记录下来,然后再把这些行和列分别处理为0即可
func setZeroes(matrix [][]int) {
// 记录所有0所在的位置[x, y],聚合这些行和列
allZeroCols := make(map[int]struct{})
allZeroRows := make(map[int]struct{})
for i := 0; i<len(matrix); i++{
for j := 0; j<len(matrix[i]); j++{
if matrix[i][j] == 0{
allZeroRows[i] = struct{}{}
allZeroCols[j] = struct{}{}
}
}
}
// 置0
for i := 0; i<len(matrix); i++{
for j := 0; j<len(matrix[i]); j++{
_, ok1 := allZeroRows[i]
_, ok2 := allZeroCols[j]
if ok1 || ok2{
matrix[i][j] = 0
}
}
}
}
但这里申请了两个额外的辅助空间,空间复杂度为O(m+n),其中 m 是矩阵中出现0值的那些行数,n 是矩阵中出现0值的那些列数
题目要求
解法二:使用两个标记变量
我们可以用矩阵的第一行和第一列作为两个标记数组(标识出现0的那些行和列),以达到 O(1) 的额外空间。但这样会导致原数组的第一行和第一列被修改,无法记录它们是否原本包含 0。因此我们需要额外使用两个标记变量分别记录第一行和第一列是否原本包含 0。
func setZeroes(matrix [][]int) {
row0, col0 := false, false // 两个变量标识第一行和第一列是否存在0
// 第一行是否存在0
for c := 0; c < len(matrix[0]); c++{
if matrix[0][c] == 0{
row0 = true
}
}
// 第一列是否存在0
for r := 0; r < len(matrix); r++{
if matrix[r][0] == 0{
col0 = true
}
}
// 接下来借助第一行和第一列的数组空间作为标记数组
// 判断右下方的子矩阵即可
for i := 1; i<len(matrix); i++{
for j := 1; j<len(matrix[0]); j++{
if matrix[i][j] == 0{
matrix[i][0] = 0 // 标记这一行需要置为0
matrix[0][j] = 0 // 标记这一列需要置为0
}
}
}
// 开始置0
for i := 1; i<len(matrix); i++{
for j := 1; j<len(matrix[0]); j++{
if matrix[i][0] == 0 || matrix[0][j] == 0{
matrix[i][j] = 0
}
}
}
if row0 {
for c := 0; c < len(matrix[0]); c++{
matrix[0][c] = 0
}
}
if col0 {
for r := 0; r < len(matrix); r++{
matrix[r][0] = 0
}
}
}