【每天学习一点算法 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)

相关推荐
田里的水稻1 小时前
OE_ubuntu24.04安装ros2
人工智能·算法·数学建模·机器人·自动驾驶
Charlie_lll1 小时前
力扣解题-无重复字符的最长子串
后端·算法·leetcode
●VON1 小时前
HarmonyOS应用开发实战(基础篇)Day12 -《打造专业级底部导航栏》
学习·华为·harmonyos·von
W133309089071 小时前
大专应用统计学专业,怎么区分数据统计岗和数据分析岗?
人工智能·算法·数据分析
羑悻的小杀马特1 小时前
LFU缓存算法全解:从双哈希+双向链表到O(1)艺术,解锁长期热点守护神
算法·缓存·哈希算法·lfu·双链表
kebijuelun1 小时前
GLM-5:从 Vibe Coding 走向 Agentic Engineering 的全栈路线图
人工智能·深度学习·算法·语言模型
有为少年1 小时前
Monarch矩阵:从设计直觉到数学推导与实际应用
人工智能·深度学习·学习·线性代数·机器学习·计算机视觉·矩阵
2501_918126911 小时前
stm32四条线,红绿黑白分别对应什么
stm32·单片机·学习·个人开发
@insist1231 小时前
软考-软件设计师-数据表示核心考点详解:从进制转换到 IEEE 754 标准
java·数据结构·算法