73. 矩阵置零

1. 题目

给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。

示例 1:

img

1
2
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

示例 2:

img

1
2
输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

提示:

  • m == matrix.length
  • n == matrix[0].length
  • 1 <= m, n <= 200
  • -231 <= matrix[i][j] <= 231 - 1

进阶:

  • 一个直观的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。
  • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
  • 你能想出一个仅使用常量空间的解决方案吗?

2. 思路

  • 题目要求矩阵中存在0的元素将其对应的行和列都统一置为0,并且要求进行原地操作
  • 常规的思维是扫描二维数组中的所有单元格,记录下值为0的单元格,并在后续统一将对应的行与列转化为0,但是这种算法的空间复杂度是O(n + m)
  • 因此考虑将矩阵的第一行和第一列用于记录该行与列是否需要进行置0操作,并将该行与列原先是否需要置0记录于firstRowContainsZerofirstColumnContainsZero变量中
  • 整个代码分为以下5步:
    • 初始化并设置firstRowContainsZero变量
    • 初始化并设置firstColumnContainsZero变量
    • 遍历除开第一行与第一列以外的所有元素,当出现值为0时,对应将首行和首列对应位置置为0,表示需要将该行/列进行置0
    • 遍历第一行与第一列的置0情况,并按照规则对需要置空的行或列进行置空(置空不需要包含第一列与第一行)
    • 检查firstRowContainsZerofirstColumnContainsZero变量,如果变量为true,则对应将首行/首列置为0

3. 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class Solution {
public void setZeroes(int[][] matrix) {
var firstRowContainsZero = false;
var firstColumnContainsZero = false;
var rows = matrix.length;
var columns = matrix[0].length;

for (var i = 0; i < rows; ++i) {
if (matrix[i][0] == 0) {
firstColumnContainsZero = true;
break;
}
}

for (var i = 0; i < columns; ++i) {
if (matrix[0][i] == 0) {
firstRowContainsZero = true;
break;
}
}

for (var i = 1; i < rows; ++i) {
for (var j = 1; j < columns; ++j) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}

for (var i = 1; i < rows; ++i) {
if (matrix[i][0] == 0) {
setZeroesAtRow(matrix, i);
}
}

for (var i = 1; i < columns; ++i) {
if (matrix[0][i] == 0) {
setZeroesAtColumn(matrix, i);
}
}

if (firstRowContainsZero) {
setZeroesAtRow(matrix, 0);
}

if (firstColumnContainsZero) {
setZeroesAtColumn(matrix, 0);
}
}

private void setZeroesAtColumn(int[][] matrix, int column) {
var rows = matrix.length;
for (var i = 0; i < rows; ++i) {
matrix[i][column] = 0;
}
}

private void setZeroesAtRow(int[][] matrix, int row) {
var columns = matrix[0].length;
for (var i = 0; i < columns; ++i) {
matrix[row][i] = 0;
}
}
}

4. 复杂度

  • 时间复杂度:O(mn)
  • 空间复杂度:O(1)

image-20230823143012181