【每天学习一点算法 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 天前
给AI一张“业务概念地图“:本体如何从哲学走向企业智能
大数据·人工智能·经验分享·笔记·学习·学习方法·政务
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
XiHongShi20161 天前
STM32F407 RTC定时器例程,建议保存
stm32·单片机·学习
爱吃苹果的日记本1 天前
离散数学第六课
学习·离散数学
猎头南楼1 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
AI职业加油站1 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
旖旎夜光1 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark1 天前
大规模并行计算中的负载均衡算法研究4
算法