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

相关推荐
代码山河2 小时前
Python就业方向全解析:后端、爬虫、数据分析、AI你选哪个?
python·学习·架构·教程·面向对象·项目
释厄6233 小时前
AI学习层更新与跨体转移律——人类社会同构·不缺理解缺 U
人工智能·学习
UIU1145 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场5 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi5 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David6 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院7 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
小嘉丶学长7 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节
niyongsheng7 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
小李不想当小白8 小时前
SPI通信外设与W25Q64 (硬件SPI)(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式