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

相关推荐
csdn_aspnet21 分钟前
Python 算法快闪 LeetCode 编号 70 - 爬楼梯
python·算法·leetcode·职场和发展
LuminousCPP1 小时前
数据结构 - 线性表第四篇:C 语言通讯录优化升级全记录(踩坑 + 思考)
c语言·开发语言·数据结构·经验分享·笔记·学习
魔法阵维护师1 小时前
从零开发游戏需要学习的c#模块,第十四章(保存和加载)
学习·游戏·c#
_李小白2 小时前
【android opencv学习笔记】Day 17: 目标追踪(MeanShift)
android·opencv·学习
一只机电自动化菜鸟2 小时前
一建机电备考笔记(40) 建筑机电施工—排水管道施工(含考频+题型)
经验分享·笔记·学习·职场和发展·课程设计
2301_818730562 小时前
numpy的学习(笔记)
学习·numpy
GHL2842710903 小时前
Logon failed, use ctrl+c to cancel basic credential prompt
学习·prompt
共享家95273 小时前
Langchain的学习(二)
学习·langchain
victory04313 小时前
agent 学习路径解析 学习资源分享
学习