LeetCode 73. 矩阵置零 空间优化题解,一题体会时间换空间、不使用额外空间。
73. 矩阵置零#
https://leetcode.cn/problems/set-matrix-zeroes/
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。
你能想出一个仅使用常量空间的解决方案吗?
逐行逐列标记0状态#
每行每列开辟一个数组,记录该行该列是否有0。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/**
* 粗暴:存零所在位置
*/
public static int[][] setZeroesBruteForce(int[][] matrix) {
boolean[] zeroRows = new boolean[matrix.length];
boolean[] zeroColumns = new boolean[matrix[0].length];
for (int row = 0; row < matrix.length; row++) {
for (int column = 0; column < matrix[row].length; column++) {
if (matrix[row][column] == 0) {
zeroRows[row] = true;
zeroColumns[column] = true;
}
}
}
for (int row = 0; row < matrix.length; row++) {
for (int column = 0; column < matrix[row].length; column++) {
if (zeroRows[row] || zeroColumns[column]) {
matrix[row][column] = 0;
}
}
}
return matrix;
}
|
复杂度分析#
遍历了两次矩阵,时间复杂度O(mn)
。
使用了额外的两个数组,一个行数大小,一个列数大小,空间复杂度大致为O(m+n)
。
使用首行首列标记0状态#
题干中希望我们使用O(1)
的空间,不开辟额外空间即为O(1)
。同时,一般时间换空间即可提升空间性能。
我们使用首行首列记录每行每列0的状态。
对于首行首列原本0的状态,我们预先遍历一次判断,后面统一处理。
这里时间复杂度提升到了O(mn+m+n)
,由于大O算法忽略低阶,因此视为与解法1一致。
这道题很适合用来理解时间换空间
、不使用额外空间。
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
66
67
68
69
|
/**
* 取巧解:
* 1. 使用0行0列记录行列0值情况,不额外申请空间
* 2. 同时提前判断0行0列原本0值的情况,使用boolean标记,最后刷新0行0列
* <p>
* 执行用时:
* 0 ms
* , 在所有 Java 提交中击败了
* 100.00%
* 的用户
* 内存消耗:
* 42.8 MB
* , 在所有 Java 提交中击败了
* 67.48%
* 的用户
* 通过测试用例:
* 164 / 164
*/
public int[][] setZeroesZeroRowCol(int[][] matrix) {
int m = matrix.length;
int n = matrix[0].length;
// 使用第一列记录该行是否需要置为0,本身某行出现了0值时,matrix[row][0]就应该==0
// 一行一列是否有0
boolean row0Zero = false;
boolean col0Zero = false;
for (int row = 0; row < m; row++) {
if (matrix[row][0] == 0) {
col0Zero = true;
break;
}
}
for (int col = 0; col < n; col++) {
if (matrix[0][col] == 0) {
row0Zero = true;
break;
}
}
// 判断 是否有0
for (int row = 1; row < m; row++) {
for (int col = 1; col < n; col++) {
if (matrix[row][col] == 0) {
matrix[row][0] = 0;
matrix[0][col] = 0;
}
}
}
// 将 第二行第二列开始 置0
for (int row = 1; row < m; row++) {
for (int col = 1; col < n; col++) {
if (matrix[row][0] == 0 || matrix[0][col] == 0) {
matrix[row][col] = 0;
}
}
}
// 处理第一行第一列
if (col0Zero) {
for (int row = 0; row < m; row++) {
matrix[row][0] = 0;
}
}
if (row0Zero) {
for (int col = 0; col < n; col++) {
matrix[0][col] = 0;
}
}
return matrix;
}
|
复杂度分析#
时间复杂度提升到了O(mn+m+n)
,由于大O算法忽略低阶,为O(mn)
。
未使用额外空间,复杂度O(1)
。