Skip to content

Commit 70dca2f

Browse files
committed
二刷73
1 parent 2efd345 commit 70dca2f

File tree

8 files changed

+312
-19
lines changed

8 files changed

+312
-19
lines changed

docs/0073-set-matrix-zeroes.adoc

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,113 @@
11
[#0073-set-matrix-zeroes]
2-
= 73. Set Matrix Zeroes
2+
= 73. 矩阵置零
33

4-
{leetcode}/problems/set-matrix-zeroes/[LeetCode - Set Matrix Zeroes^]
4+
https://leetcode.cn/problems/set-matrix-zeroes/[LeetCode - 73. 矩阵置零^]
55

6-
Given a _m_ x _n_ matrix, if an element is 0, set its entire row and column to 0. Do it https://en.wikipedia.org/wiki/In-place_algorithm[*in-place*^].
6+
给定一个 `m x n` 的矩阵,如果一个元素为 *0*,则将其所在行和列的所有元素都设为 *0* 。请使用 *http://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95[原地]* 算法。
77

8-
*Example 1:*
8+
*示例 1:*
99

10-
[subs="verbatim,quotes,macros"]
11-
----
12-
*Input:*
10+
image::images/0073-01.jpg[{image_attr}]
11+
12+
....
13+
输入:matrix =
1314
[
1415
[1,1,1],
1516
[1,0,1],
1617
[1,1,1]
1718
]
18-
*Output:*
19+
20+
输出:
1921
[
2022
[1,0,1],
2123
[0,0,0],
2224
[1,0,1]
2325
]
24-
----
26+
....
2527

26-
*Example 2:*
28+
*示例 2:*
2729

28-
[subs="verbatim,quotes,macros"]
29-
----
30-
*Input:*
30+
image::images/0073-02.jpg[{image_attr}]
31+
32+
....
33+
输入:matrix =
3134
[
3235
[0,1,2,0],
3336
[3,4,5,2],
3437
[1,3,1,5]
3538
]
36-
*Output:*
39+
40+
输出:
3741
[
3842
[0,0,0,0],
3943
[0,4,5,0],
4044
[0,3,1,0]
4145
]
42-
----
46+
....
47+
48+
*提示:*
4349

44-
*Follow up:*
50+
* `m == matrix.length`
51+
* `n == matrix[0].length`
52+
* `1 \<= m, n \<= 200`
53+
* `-2^31^ \<= matrix[i][j] \<= 2^31^ - 1`
4554
55+
*进阶:*
4656

47-
* A straight forward solution using O(_m__n_) space is probably a bad idea.
48-
* A simple improvement uses O(_m_ + _n_) space, but still not the best solution.
49-
* Could you devise a constant space solution?
57+
* 一个直观的解决方案是使用 stem:[O(mn)] 的额外空间,但这并不是一个好的解决方案。
58+
* 一个简单的改进方案是使用 stem:[O(m + n)] 的额外空间,但这仍然不是最好的解决方案。
59+
* 你能想出一个仅使用常量空间的解决方案吗?
5060
5161
62+
== 思路分析
5263

64+
最简单的办法就是记录出现 `0` 的行号和列号,最后根据行号和列号设置 `0`。取巧的办法是把出现 `0` 的位置在首行和首列标记一下,首行和首列需要首先检查一下是否已经包含 `0`,最后再单独处理首行和首列。
65+
66+
image::images/0073-10.png[{image_attr}]
5367

5468
[[src-0073]]
69+
[tabs]
70+
====
71+
一刷::
72+
+
73+
--
5574
[{java_src_attr}]
5675
----
5776
include::{sourcedir}/_0073_SetMatrixZeroes.java[tag=answer]
5877
----
78+
--
79+
80+
二刷(路标)::
81+
+
82+
--
83+
[{java_src_attr}]
84+
----
85+
include::{sourcedir}/_0073_SetMatrixZeroes_20.java[tag=answer]
86+
----
87+
--
88+
89+
二刷(位元素 )::
90+
+
91+
--
92+
[{java_src_attr}]
93+
----
94+
include::{sourcedir}/_0073_SetMatrixZeroes_21.java[tag=answer]
95+
----
96+
--
97+
98+
二刷(头部标记)::
99+
+
100+
--
101+
[{java_src_attr}]
102+
----
103+
include::{sourcedir}/_0073_SetMatrixZeroes_22.java[tag=answer]
104+
----
105+
--
106+
====
107+
108+
109+
== 参考资料
59110

111+
. https://leetcode.cn/problems/set-matrix-zeroes/solutions/3799648/yi-bu-bu-you-hua-cong-omn-dao-o1-kong-ji-fdgt/[73. 矩阵置零 - 一步步优化,从 O(m+n) 到 O(1) 空间^]
112+
. https://leetcode.cn/problems/set-matrix-zeroes/solutions/669901/ju-zhen-zhi-ling-by-leetcode-solution-9ll7/[73. 矩阵置零 - 官方题解^]
113+
. https://leetcode.cn/problems/set-matrix-zeroes/solutions/670392/xiang-jie-ge-chong-kong-jian-fu-za-du-de-y4pd/[73. 矩阵置零 - 详解各种空间复杂度的解法^]

docs/images/0073-01.jpg

13.5 KB
Loading

docs/images/0073-02.jpg

21.1 KB
Loading

docs/images/0073-10.png

104 KB
Loading

logbook/202503.adoc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,11 @@ endif::[]
19441944
|{doc_base_url}/0074-search-a-2d-matrix.adoc[题解]
19451945
|✅ 二分查找。通过将矩阵容量转换成坐标,把矩阵按行“拼接”,使用二分查找来处理,解法非常妙。也可以使用 {doc_base_url}/0240-search-a-2d-matrix-ii.adoc[240. 搜索二维矩阵 II^] 类似的解法,从左下角或者右上角开始,排除行或列来解答。
19461946

1947+
|{counter:codes2503}
1948+
|{leetcode_base_url}/set-matrix-zeroes/[73. Set Matrix Zeroes^]
1949+
|{doc_base_url}/0073-set-matrix-zeroes.adoc[题解]
1950+
|✅ 矩阵。最简单的办法就是记录出现 `0` 的行号和列号,最后根据行号和列号设置 `0`。取巧的办法是把出现 `0` 的位置在首行和首列标记一下,首行和首列需要首先检查一下是否已经包含 `0`,最后再单独处理首行和首列。
1951+
19471952
|===
19481953

19491954
截止目前,本轮练习一共完成 {codes2503} 道题。
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.diguage.algo.leetcode;
2+
3+
import java.util.HashSet;
4+
import java.util.Set;
5+
6+
public class _0073_SetMatrixZeroes_20 {
7+
// tag::answer[]
8+
/**
9+
* @author D瓜哥 · https://www.diguage.com
10+
* @since 2025-11-19 20:32
11+
*/
12+
public void setZeroes(int[][] matrix) {
13+
int m = matrix.length;
14+
int n = matrix[0].length;
15+
// 记录 行号和列号,最后按照行号和列号来进行处理
16+
Set<String> zeros = new HashSet<>();
17+
for (int r = 0; r < m; r++) {
18+
for (int c = 0; c < n; c++) {
19+
if (matrix[r][c] == 0) {
20+
zeros.add("r" + r);
21+
zeros.add("c" + c);
22+
}
23+
}
24+
}
25+
for (int r = 0; r < m; r++) {
26+
for (int c = 0; c < n; c++) {
27+
if (zeros.contains("r" + r) || zeros.contains("c" + c)) {
28+
matrix[r][c] = 0;
29+
}
30+
}
31+
}
32+
}
33+
// end::answer[]
34+
35+
static void main() {
36+
int[][] matrix5 = {{1, 0}};
37+
// int[][] matrix5 = {
38+
// {1, 1, 1},
39+
// {1, 0, 1},
40+
// {32, 1, 1}};
41+
// int[][] matrix5 = {
42+
// {0, 1, 2, 0},
43+
// {3, 4, 5, 2},
44+
// {1, 3, 1, 5}};
45+
// int[][] matrix5 = {
46+
// {8, 3, 6, 9, 7, 8, 0, 6},
47+
// {0, 3, 7, 0, 0, 4, 3, 8},
48+
// {5, 3, 6, 7, 1, 6, 2, 6},
49+
// {8, 7, 2, 5, 0, 6, 4, 0},
50+
// {0, 2, 9, 9, 3, 9, 7, 3}};
51+
new _0073_SetMatrixZeroes_20()
52+
.setZeroes(matrix5);
53+
}
54+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package com.diguage.algo.leetcode;
2+
3+
import java.util.Arrays;
4+
5+
public class _0073_SetMatrixZeroes_21 {
6+
// tag::answer[]
7+
/**
8+
* @author D瓜哥 · https://www.diguage.com
9+
* @since 2025-11-19 21:18
10+
*/
11+
public void setZeroes(int[][] matrix) {
12+
// 从数中找缺失的数字,使用缺失的数字作为占位符来处理
13+
// 处理其他太费劲了。而且,细节太多,极易出错。
14+
int m = matrix.length;
15+
int n = matrix[0].length;
16+
int size = m * n % 32 == 0 ? m * n / 32 : m * n / 32 + 1;
17+
int cap = size * 32;
18+
// 使用位来标记哪个数字出现过
19+
int[] data = new int[size];
20+
Arrays.fill(data, 0);
21+
for (int[] ints : matrix) {
22+
for (int r = 0; r < n; r++) {
23+
int num = ints[r];
24+
if (num >= cap || num < 0) {
25+
continue;
26+
}
27+
int index = num / 32;
28+
int rem = num % 32;
29+
data[index] |= (1 << rem);
30+
}
31+
}
32+
int placeholder = cap + 2;
33+
for (int i = 0; i < data.length; i++) {
34+
int bits = data[i];
35+
for (int j = 0; j < 32; j++) {
36+
// 第一个未出现的数字就是可用的占位符
37+
if (((bits >>> j) & 1) == 0) {
38+
placeholder = i * 32 + j;
39+
break;
40+
}
41+
}
42+
if (placeholder != cap + 2) {
43+
break;
44+
}
45+
}
46+
47+
// 先将出现0的行列使用占位符数字标记
48+
for (int c = 0; c < m; c++) {
49+
for (int r = 0; r < n; r++) {
50+
if (matrix[c][r] == 0) {
51+
for (int ic = 0; ic < m; ic++) {
52+
if (matrix[ic][r] != 0) {
53+
matrix[ic][r] = placeholder;
54+
}
55+
}
56+
for (int ir = 0; ir < n; ir++) {
57+
if (matrix[c][ir] != 0) {
58+
matrix[c][ir] = placeholder;
59+
}
60+
}
61+
}
62+
}
63+
}
64+
// 再统一修改为 0
65+
for (int c = 0; c < m; c++) {
66+
for (int r = 0; r < n; r++) {
67+
if (matrix[c][r] == placeholder) {
68+
matrix[c][r] = 0;
69+
}
70+
}
71+
}
72+
}
73+
// end::answer[]
74+
75+
static void main() {
76+
int[][] matrix5 = {{1, 0}};
77+
// int[][] matrix5 = {
78+
// {1, 1, 1},
79+
// {1, 0, 1},
80+
// {32, 1, 1}};
81+
// int[][] matrix5 = {
82+
// {0, 1, 2, 0},
83+
// {3, 4, 5, 2},
84+
// {1, 3, 1, 5}};
85+
// int[][] matrix5 = {
86+
// {8, 3, 6, 9, 7, 8, 0, 6},
87+
// {0, 3, 7, 0, 0, 4, 3, 8},
88+
// {5, 3, 6, 7, 1, 6, 2, 6},
89+
// {8, 7, 2, 5, 0, 6, 4, 0},
90+
// {0, 2, 9, 9, 3, 9, 7, 3}};
91+
new _0073_SetMatrixZeroes_21()
92+
.setZeroes(matrix5);
93+
}
94+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.diguage.algo.leetcode;
2+
3+
public class _0073_SetMatrixZeroes_22 {
4+
// tag::answer[]
5+
6+
/**
7+
* @author D瓜哥 · https://www.diguage.com
8+
* @since 2025-11-19 22:32
9+
*/
10+
public void setZeroes(int[][] matrix) {
11+
int m = matrix.length;
12+
int n = matrix[0].length;
13+
// 第一列有没有 0
14+
boolean rowHasZero = false;
15+
for (int c = 0; c < m; c++) {
16+
if (matrix[c][0] == 0) {
17+
rowHasZero = true;
18+
break;
19+
}
20+
}
21+
// 第一行有没有 0
22+
boolean colHasZero = false;
23+
for (int r = 0; r < n; r++) {
24+
if (matrix[0][r] == 0) {
25+
colHasZero = true;
26+
}
27+
}
28+
29+
// 将出现的 0 首行和首列标记一下
30+
for (int c = 1; c < m; c++) {
31+
for (int r = 1; r < n; r++) {
32+
if (matrix[c][r] == 0) {
33+
matrix[c][0] = 0;
34+
matrix[0][r] = 0;
35+
}
36+
}
37+
}
38+
// 根据首行和首列来修改为 0
39+
for (int c = 1; c < m; c++) {
40+
if (matrix[c][0] == 0) {
41+
for (int r = 1; r < n; r++) {
42+
matrix[c][r] = 0;
43+
}
44+
}
45+
}
46+
for (int r = 1; r < n; r++) {
47+
if (matrix[0][r] == 0) {
48+
for (int c = 1; c < m; c++) {
49+
matrix[c][r] = 0;
50+
}
51+
}
52+
}
53+
// 最后处理首行和首列
54+
if (colHasZero) {
55+
for (int r = 0; r < n; r++) {
56+
matrix[0][r] = 0;
57+
}
58+
}
59+
if (rowHasZero) {
60+
for (int c = 0; c < m; c++) {
61+
matrix[c][0] = 0;
62+
}
63+
}
64+
}
65+
// end::answer[]
66+
67+
static void main() {
68+
int[][] matrix5 = {{1, 0}};
69+
// int[][] matrix5 = {
70+
// {1, 1, 1},
71+
// {1, 0, 1},
72+
// {32, 1, 1}};
73+
// int[][] matrix5 = {
74+
// {0, 1, 2, 0},
75+
// {3, 4, 5, 2},
76+
// {1, 3, 1, 5}};
77+
// int[][] matrix5 = {
78+
// {8, 3, 6, 9, 7, 8, 0, 6},
79+
// {0, 3, 7, 0, 0, 4, 3, 8},
80+
// {5, 3, 6, 7, 1, 6, 2, 6},
81+
// {8, 7, 2, 5, 0, 6, 4, 0},
82+
// {0, 2, 9, 9, 3, 9, 7, 3}};
83+
new _0073_SetMatrixZeroes_22()
84+
.setZeroes(matrix5);
85+
}
86+
}

0 commit comments

Comments
 (0)