每天学习一点算法 2026/02/24
题目:矩阵置零
给定一个
m x n的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法**。**
示例 1:

示例 2:

-
如果我们遍历矩阵,遇到 0 时就将当前行列的的数字都置为 0 ,这样做的话会遇到一个问题,我们后续遍历遇到的 0 不能确定是我们置零后的还是初始的,最容易想到的方法就是我们利用两个数组记录初始矩阵的每个行列是否有 0。
typescriptfunction setZeroes(matrix: number[][]): void { const m = matrix.length const n = matrix[0].length const row = new Array(m).fill(false) // 用于记录矩阵行是否有 0 const col = new Array(n).fill(false) // 用于记录矩阵列是否有 0 // 先遍历一次矩阵 记录初始矩阵的每个行列是否有 0 for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (matrix[i][j] === 0) { row[i] = col[j] = true } } } // 再次遍历 根据标记数组完成置零 for (let i = 0; i < m; i++) { for (let j = 0; j < n; j++) { if (row[i] || col[j]) { matrix[i][j] = 0 } } } }; -
我们可以思考一下是否有办法可以减少空间复杂度,如果我们使用第一行和第一列作为标记数组,先遍历剩余部分矩阵标记第一行和第一列,再根据第一行和第一列的标记情况将剩余部分矩阵置零,但是要注意标记时会影响第一行和第一列的初始 0 的状态,所以我们需要两个变量来记录第一行和第一列初始是否有 0。
typescriptfunction setZeroes(matrix: number[][]): void { const m = matrix.length const n = matrix[0].length let rowFlag = false, colFlag = false // 用于记录初始第一行和第一列的是否有 0 // 记录第一列是否有 0 for (let i = 0; i < m; i++) { if (matrix[i][0] === 0) { colFlag = true break } } // 记录第一行是否有 0 for (let j = 0; j < n; j++) { if (matrix[0][j] === 0) { rowFlag = true break } } // 遍历剩余部分矩阵数据 标记有 0 的行列 for (let i = 1; i < m; i++) { for (let j = 1; j < n; j++) { if (matrix[i][j] === 0) { // 如果遇到 0,将第一列对应行和第一行对应列标为 0 matrix[i][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 } } } // 如果初始第一列有 0 将第一列都置为0 if (colFlag) { for (let i = 0; i < m; i++) { matrix[i][0] = 0; } } // 如果初始第一行有 0 将第一行都置为0 if (rowFlag) { for (let j = 0; j < n; j++) { matrix[0][j] = 0; } } }; -
在第二种方法的基础上还可以再次做优化,我们可以注意到,我利用第一行和第一列做标记时
[0, 0]位置其实是浪费了的,我们完全可以利用这个位置来标记第一行初始有没有 0,这样我们就只需要一个遍历来记录第一列是否有 0 就可以完成置零了(注意:因为第一行是作为标记行,我们需要放到最后做置零操作)。typescriptfunction setZeroes(matrix: number[][]): void { const m = matrix.length const n = matrix[0].length let colFlag = false // 用于记录初始第一列的是否有 0 for (let i = 0; i < m; i++) { if (matrix[i][0] === 0 && !colFlag) { // 标记初始第一行是否有0 colFlag = true } for (let j = 1; j < n; j++) { // 利用第一行和第一列标记行列初始是否有0 // 如果第一行有0,matrix[0][0]会被标记为 0 if (matrix[i][j] === 0) { matrix[i][0] = matrix[0][j] = 0 } } } // 根据第一行和第一列的标记情况,对矩阵置零(第一行作为标记需要放到最后处理) for (let i = m - 1; i >= 0; i--) { for (let j = 1; j < n; j++) { if (matrix[i][0] === 0 || matrix[0][j] === 0) { matrix[i][j] = 0 } } if (colFlag) { matrix[i][0] = 0 } } };
题目来源:力扣(LeetCode)