当前位置: 首页 > news >正文

算法73. 矩阵置零

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

示例 1:在这里插入图片描述输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]
示例2:
在这里插入图片描述输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

解法:

class Solution:def setZeroes(self, matrix: List[List[int]]) -> None:"""Do not return anything, modify matrix in-place instead."""if not matrix or not matrix[0]:returnm,n=len(matrix),len(matrix[0])# 1. 检查第一行/第一列是否原本就有0first_row_has_zero = any(matrix[0][j]==0 for j in range(n))first_col_has_zero = any(matrix[i][0]==0 for i in range(m))# 2. 用第一行和第一列作为“标记数组”# 也就是把要置为0的行列标记出来for i in range(1,m):for j in range(1,n):if matrix[i][j]==0:matrix[i][0] = 0matrix[0][j] = 0# 3. 根据标记,把中间部分(非第一行/列)置零for i in range(1,m):if matrix[i][0] == 0:# 找到要置零的行,全部置零for j in range(1,n):matrix[i][j] = 0for j in range(1,n):if matrix[0][j] == 0:for i in range(1,m):matrix[i][j] = 0# 4. 最后再处理第一行和第一列if first_row_has_zero:for j in range(n):matrix[0][j] = 0if first_col_has_zero:for i in range(m):matrix[i][0] = 0 

使用5x5的矩阵来完整演示这个算法的每一步执行过程如下:


📌 示例矩阵:

原始矩阵:
[[ 1,  2,  3,  4,  5],[ 6,  7,  0,  8,  9],[10, 11, 12, 13, 14],[15,  0, 16, 17, 18],[19, 20, 21, 22, 23]
]

目标:如果某个元素是 0,就把它所在的整行和整列都设为 0。

我们使用 O(1) 空间优化算法(用第一行/列做标记)。


✅ 步骤 1:判断第一行和第一列是否原本有 0

first_row_has_zero = any(matrix[0][j] == 0 for j in range(5))False
first_col_has_zero = any(matrix[i][0] == 0 for i in range(5))False

第一行:[1,2,3,4,5] → 没有 0
第一列:[1,6,10,15,19] → 没有 0

✅ 所以最后我们不会主动清零第一行和第一列,除非标记需要。


✅ 步骤 2:用第一行和第一列作为“标记位”

我们从 (1,1) 开始扫描(跳过第一行和第一列),发现 0 就在 matrix[i][0]matrix[0][j] 打标记。

for i in range(1, 5):for j in range(1, 5):if matrix[i][j] == 0:matrix[i][0] = 0      # 标记第 i 行要清零matrix[0][j] = 0      # 标记第 j 列要清零

我们找到两个 0:

  1. matrix[1][2] == 0 → 第1行第2列是0

    • matrix[1][0] = 0 → 标记第1行要清零
    • matrix[0][2] = 0 → 标记第2列要清零
  2. matrix[3][1] == 0 → 第3行第1列是0

    • matrix[3][0] = 0 → 标记第3行要清零
    • matrix[0][1] = 0 → 标记第1列要清零

👉 打完标记后,矩阵变成:

[[ 1,  0,  0,  4,  5],   ← matrix[0][1]=0(第1列要清零),matrix[0][2]=0(第2列要清零)[ 0,  7,  0,  8,  9],   ← matrix[1][0]=0(第1行要清零)[10, 11, 12, 13, 14],[ 0,  0, 16, 17, 18],   ← matrix[3][0]=0(第3行要清零)[19, 20, 21, 22, 23]
]

🔔 注意:我们故意修改了第一行和第一列,把它们当作“标记墙”。


✅ 步骤 3:根据标记清零“中间部分”(非第一行/列)

① 清零被标记的行(从第1行开始)

for i in range(1, 5):if matrix[i][0] == 0:   # 第 i 行被标记了for j in range(1, 5):  # 把 j ≥ 1 的列清零matrix[i][j] = 0
  • i=1: matrix[1][0]==0 → 清零 matrix[1][1]matrix[1][4]
  • i=3: matrix[3][0]==0 → 清零 matrix[3][1]matrix[3][4]

当前矩阵:

[[ 1,  0,  0,  4,  5],[ 0,  0,  0,  0,  0],   ← 第1行清零(除了 matrix[1][0] 已是0)[10, 11, 12, 13, 14],[ 0,  0,  0,  0,  0],   ← 第3行清零[19, 20, 21, 22, 23]
]

② 清零被标记的列(从第1列开始)

for j in range(1, 5):if matrix[0][j] == 0:   # 第 j 列被标记了for i in range(1, 5):  # 把 i ≥ 1 的行清零matrix[i][j] = 0
  • j=1: matrix[0][1]==0 → 清零第1列(i=1 到 4)
  • j=2: matrix[0][2]==0 → 清零第2列(i=1 到 4)

注意:matrix[1][1], [1][2], [3][1], [3][2] 已是 0,但其他也要清:

  • 第1列:matrix[2][1], matrix[4][1] → 设为 0
  • 第2列:matrix[2][2], matrix[4][2] → 设为 0

当前矩阵:

[[ 1,  0,  0,  4,  5],[ 0,  0,  0,  0,  0],[10,  0,  0, 13, 14],   ← matrix[2][1] 和 [2][2] 被清零[ 0,  0,  0,  0,  0],[19,  0,  0, 22, 23]    ← matrix[4][1] 和 [4][2] 被清零
]

✅ 步骤 4:最后处理第一行和第一列

if first_row_has_zero:False → 不清零第一行for j in range(5): matrix[0][j] = 0if first_col_has_zero:False → 不清零第一列for i in range(5): matrix[i][0] = 0

所以第一行和第一列保持原样。


✅ 最终结果:

[[ 1,  0,  0,  4,  5],[ 0,  0,  0,  0,  0],[10,  0,  0, 13, 14],[ 0,  0,  0,  0,  0],[19,  0,  0, 22, 23]
]

✅ 验证是否正确?

原始 0 的位置:

  • (1,2) → 第1行、第2列 → 应清零 → ✅
  • (3,1) → 第3行、第1列 → 应清零 → ✅

结果:

  • 第1行全0 → ✅
  • 第3行全0 → ✅
  • 第1列:matrix[i][1] 全为0(i≥1)→ ✅
  • 第2列:matrix[i][2] 全为0(i≥1)→ ✅
  • 第一行和第一列未被误清 → ✅

✅ 总结:算法全过程

步骤操作目的
1检查第一行/列是否有 0保存原始信息
2扫描内部,用 matrix[i][0]matrix[0][j] 打标记空间复用,O(1)
3根据 matrix[i][0]==0 清零行读标记,清零中间行
4根据 matrix[0][j]==0 清零列读标记,清零中间列
5最后根据 first_row/col_has_zero 清零第一行/列保证完整性

💡 关键点回顾

  • matrix[i][0] == 0 确实是被前面改过的,但这是设计好的标记机制
  • 我们不是在“错误地读修改后的值”,而是在“正确地读标记”
  • 这就是 O(1) 空间解法的精髓用矩阵自己当哈希表

http://www.dtcms.com/a/326025.html

相关文章:

  • MySQL权限管理和MySQL备份
  • 银行客户经营:用企业微信精准破解触达断层、效率瓶颈、数据孤岛三个痛点
  • GPT-5 全面解析与最佳实践指南
  • 容器 K8S Docker Kata 学习(一)
  • idea三个环境变量设置
  • Spring Boot Excel数据导入数据库实现详解
  • Spring-Security-5.7.11升级6.5.2
  • Socket(套接字)网络编程
  • Scala异步任务编排与弹性容错机制
  • [特殊字符]走进标杆工厂参观研学| 破茧成蝶的感悟之旅
  • Spring Boot 中 @Transactional 解析
  • Spring Boot启动事件详解:类型、监听与实战应用
  • PyCharm(2025.1.3.1)绑定 Conda 环境
  • SoftCnKiller:绿色小巧,流氓软件一键扫描!
  • 得物,三七互娱,游卡快手26秋招内推
  • 麒麟系统使用-PATH设置
  • 【Figma】Figma基础笔记二,常用快捷键和操作
  • 集成电路学习:什么是URDF Model统一机器人描述格式模型
  • 红队快速打包,通过 Sharp4CompressArchive 一键定制化压缩文件
  • “一车一码一池一充”:GB 17761-2024新国标下电动自行车的安全革命
  • gophis钓鱼流程
  • 企业内外网物理隔离时文件怎么传输更安全
  • 算法基础 1
  • 【排序算法】⑦归并排序
  • 模拟多重循环解决逻辑问题
  • Mysql系列--6、内置函数
  • 横向越权:修改参数访问不属于自己的数据
  • LeetCode——241.为运算表达式设计优先级
  • 【Maven】02 - 进阶篇
  • Spark AI 算力通平台全球正式上线,引领算力新时代