【每天学习一点算法 2026/02/24】矩阵置零

每天学习一点算法 2026/02/24

题目:矩阵置零

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

示例 1:

示例 2:

  1. 如果我们遍历矩阵,遇到 0 时就将当前行列的的数字都置为 0 ,这样做的话会遇到一个问题,我们后续遍历遇到的 0 不能确定是我们置零后的还是初始的,最容易想到的方法就是我们利用两个数组记录初始矩阵的每个行列是否有 0。

    typescript 复制代码
    function 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
          }
        }
      }
    };
  2. 我们可以思考一下是否有办法可以减少空间复杂度,如果我们使用第一行和第一列作为标记数组,先遍历剩余部分矩阵标记第一行和第一列,再根据第一行和第一列的标记情况将剩余部分矩阵置零,但是要注意标记时会影响第一行和第一列的初始 0 的状态,所以我们需要两个变量来记录第一行和第一列初始是否有 0。

    typescript 复制代码
    function 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;
        }
      }
    };
  3. 在第二种方法的基础上还可以再次做优化,我们可以注意到,我利用第一行和第一列做标记时 [0, 0] 位置其实是浪费了的,我们完全可以利用这个位置来标记第一行初始有没有 0,这样我们就只需要一个遍历来记录第一列是否有 0 就可以完成置零了(注意:因为第一行是作为标记行,我们需要放到最后做置零操作)。

    typescript 复制代码
    function 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)

相关推荐
得物技术11 分钟前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六4 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术4 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize5 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
罗西的思考18 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl