73. 矩阵置零
!abstract 一句话本质 先记录原始矩阵中哪些行、哪些列含有 0,再统一清零;优化版用第一行和第一列保存标记。
!quote 链接
题目
给定一个矩阵,如果某个元素为 0,就将它所在的行和列全部设为 0,并且要求原地修改。
思路(从暴力到最优)
直接在第一次遍历时清零会产生新的 0,后续扫描可能把新 0 当成原始 0,导致清零范围不断扩大。因此需要先记录,再修改。
第一版使用两个数组:rowHasZero[i] 表示第 i 行原本是否含有 0,colHasZero[j] 表示第 j 列原本是否含有 0。第二次遍历时,如果当前行或当前列被标记,就把当前位置设为 0。
第二版把第一行和第一列当作标记数组:发现内部位置为 0 时,将对应行的第一个元素和对应列的第一个元素设为 0。由于第一行和第一列既要保存标记,又可能原本含有 0,所以先用 firstRowHasZero 和 firstColHasZero 保存它们的原始状态。内部区域处理完成后,最后再处理第一行和第一列。
关键卡点
!warning 我当时卡在这
- 一开始不熟悉矩阵,不清楚如何同时处理行和列。
- 第二版的关键是区分原始的 0 和作为标记产生的 0,第一行和第一列必须最后处理。
- 这道题耗时约 20 分钟,其中包括看题解的时间,难度感受为卡住了。
代码
js
var setZeroes = function(matrix) {
let m = matrix.length;
let n = matrix[0].length;
const firstRowHasZero = matrix[0].includes(0);
const firstColHasZero = matrix.some(row => row[0] === 0);
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
if (matrix[i][j] === 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for (let i = 1; i < m; i++) {
for (let j = 1; j < n; j++) {
if (matrix[i][0] === 0 || matrix[0][j] === 0) {
matrix[i][j] = 0;
}
}
}
if (firstColHasZero) {
for (const row of matrix) {
row[0] = 0;
}
}
if (firstRowHasZero) {
matrix[0].fill(0);
}
};
复杂度
- 时间:O(mn)
- 空间:O(1)
一句话记忆点
!tip 下次看到类似题 第一行、第一列做标记,内部区域先清零,第一行和第一列最后处理。
相似题 / 套用模板
- 矩阵遍历:先明确行列下标,再分别处理边界和内部区域。
- 原地修改:优先考虑能否复用输入数组保存状态。
复习记录
2026-07-28 第 1 次复习
结果:通过 ✅(阶段 0→1)
记得牢:
- 核心思路:用第一行第一列做标记矩阵。
- 预存第一行和第一列原始是否有 0,最后单独处理。
- 代码细节正确,标记和清零的两层循环顺序完全对。
需要加强:
- 无,整体掌握很好。