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

【力扣100题】22. 矩阵置零

一、题目描述给定一个 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]]提示m matrix.lengthn matrix[0].length1 m, n 200-2^31 matrix[i][j] 2^31 - 1进阶一个直观的解决方案是使用 O(mn) 的额外空间但这并不是一个好的解决方案一个简单的改进方案是使用 O(m n) 的额外空间但这仍然不是最好的解决方案你能想出一个仅使用常量空间的解决方案吗二、解题思路总览核心问题如何记录哪些行和列需要置零同时不破坏原矩阵解决方案两次遍历 额外数组记录遍历操作第一次遍历扫描整个矩阵遇到 0 就记录该行该列需要置零第二次遍历根据记录将对应行和列的所有元素置零方案时间复杂度空间复杂度暴力解每个0都遍历行列O(mn * (mn))O(1)额外数组记录本题O(mn)O(mn)原地算法进阶O(mn)O(1)三、完整代码classSolution{public:voidsetZeroes(vectorvectorintmatrix){intmmatrix.size();intnmatrix[0].size();vectorintrow(m,0);// 记录哪些行需要置零vectorintcol(n,0);// 记录哪些列需要置零// 第一次遍历扫描矩阵记录需要置零的行和列for(inti0;im;i){for(intj0;jn;j){if(matrix[i][j]0){row[i]1;col[j]1;}}}// 第二次遍历根据记录将对应行和列置零for(inti0;im;i){for(intj0;jn;j){if(row[i]||col[j]){matrix[i][j]0;}}}}};四、算法流程图4.1 整体流程输入matrixm x n 矩阵 [Step 1] 获取矩阵尺寸 m matrix.size() n matrix[0].size() | v [Step 2] 创建辅助数组 row vectorint(m, 0) col vectorint(n, 0) | v [Step 3] 第一次遍历扫描并标记 | v for i 0 to m-1: for j 0 to n-1: matrix[i][j] 0 ? |是 |否 v v row[i] 1 继续 col[j] 1 | | v ---- 继续内层循环 -- | v 内层循环结束 | v 回到外层循环或下一步 | v [Step 4] 第二次遍历置零 | v for i 0 to m-1: for j 0 to n-1: row[i] || col[j] ? |是 |否 v v matrix[i][j] 0 继续不变 | | v v 【返回】 【返回】4.2 第一次遍历标记详细流程外层循环i 0 to m-1 内层循环j 0 to n-1 | v matrix[i][j] 0 ? |否 v 继续 j |是 v row[i] 1 col[j] 1 | v 继续 j 内层循环 j 结束后 | v i 继续外层循环 所有遍历完成后 row 数组标记了所有含 0 的行 col 数组标记了所有含 0 的列4.3 第二次遍历置零详细流程外层循环i 0 to m-1 内层循环j 0 to n-1 | v row[i] 1 或 col[j] 1 |是 v matrix[i][j] 0 | v 继续 j |否该位置不变 | v 继续 j 内层循环 j 结束后 | v i 继续外层循环4.4 具体示例执行流程输入矩阵 [[1, 1, 1], [1, 0, 1], [1, 1, 1]] m 3, n 3 row [0, 0, 0] col [0, 0, 0] 第一次遍历标记 i0, j0: matrix[0][0]1 ! 0 → 跳过 i0, j1: matrix[0][1]1 ! 0 → 跳过 i0, j2: matrix[0][2]1 ! 0 → 跳过 i1, j0: matrix[1][0]1 ! 0 → 跳过 i1, j1: matrix[1][1]0 0 → row[1]1, col[1]1 i1, j2: matrix[1][2]1 ! 0 → 跳过 i2, j0: matrix[2][0]1 ! 0 → 跳过 i2, j1: matrix[2][1]1 ! 0 → 跳过 i2, j2: matrix[2][2]1 ! 0 → 跳过 标记结果 row [0, 1, 0] col [0, 1, 0] 第二次遍历置零 i0, j0: row[0]0 且 col[0]0 → 保持 1 i0, j1: row[0]0 但 col[1]1 → 置零 i0, j2: row[0]0 且 col[2]0 → 保持 1 i1, j0: row[1]1 → 置零 i1, j1: row[1]1 且 col[1]1 → 置零 i1, j2: row[1]1 → 置零 i2, j0: row[2]0 且 col[0]0 → 保持 1 i2, j1: row[2]0 但 col[1]1 → 置零 i2, j2: row[2]0 且 col[2]0 → 保持 1 输出矩阵 [[1, 0, 1], [0, 0, 0], [1, 0, 1]]五、逐行解析5.1 创建辅助数组vectorintrow(m,0);// 记录哪些行需要置零初始化全为 0vectorintcol(n,0);// 记录哪些列需要置零初始化全为 0原理用两个一维数组分别记录需要置零的行和列。数组下标对应行号或列号值为 1 表示需要置零。空间复杂度O(m n)5.2 第一次遍历标记for(inti0;im;i){for(intj0;jn;j){if(matrix[i][j]0){row[i]1;col[j]1;}}}原理遍历整个矩阵找到所有值为 0 的元素将其所在行和列标记。时间复杂度O(m * n)5.3 第二次遍历置零for(inti0;im;i){for(intj0;jn;j){if(row[i]||col[j]){matrix[i][j]0;}}}原理再次遍历矩阵如果当前元素所在行或列被标记过row[i] || col[j] 为真则将该元素置零。逻辑只要行被标记 OR 列被标记该元素就需要置零。六、进阶原地算法 O(1) 空间6.1 核心思想用矩阵的第一行和第一列作为标记数组代替 row 和 col 的作用。问题如何区分「原本就是 0」和「被置零后变成 0」解决方案在遍历前先判断第一行和第一列是否需要置零然后用它们作为标记。6.2 进阶代码classSolution{public:voidsetZeroes(vectorvectorintmatrix){intmmatrix.size();intnmatrix[0].size();// 判断第一行和第一列是否需要置零boolfirstRowZerofalse;boolfirstColZerofalse;for(intj0;jn;j){if(matrix[0][j]0){firstRowZerotrue;break;}}for(inti0;im;i){if(matrix[i][0]0){firstColZerotrue;break;}}// 用第一行和第一列作为标记for(inti1;im;i){for(intj1;jn;j){if(matrix[i][j]0){matrix[i][0]0;// 标记第 i 行matrix[0][j]0;// 标记第 j 列}}}// 根据标记置零跳过第一行和第一列for(inti1;im;i){for(intj1;jn;j){if(matrix[i][0]0||matrix[0][j]0){matrix[i][j]0;}}}// 处理第一行和第一列if(firstRowZero){for(intj0;jn;j){matrix[0][j]0;}}if(firstColZero){for(inti0;im;i){matrix[i][0]0;}}}};6.3 进阶流程图[Step 1] 判断第一行是否含 0 firstRowZero matrix[0][j] 0 | v [Step 2] 判断第一列是否含 0 firstColZero matrix[i][0] 0 | v [Step 3] 用第一行和第一列作为标记数组 for i 1 to m-1: for j 1 to n-1: matrix[i][j] 0 |是 v matrix[i][0] 0 // 标记行 matrix[0][j] 0 // 标记列 | v [Step 4] 根据标记置零排除第一行第一列 for i 1 to m-1: for j 1 to n-1: matrix[i][0] 0 或 matrix[0][j] 0 |是 v matrix[i][j] 0 | v [Step 5] 处理第一行 firstRowZero |是 v matrix[0][j] 0 for all j | v [Step 6] 处理第一列 firstColZero |是 v matrix[i][0] 0 for all i6.4 三种方案对比方案时间复杂度空间复杂度特点暴力解O(mn * (mn))O(1)每个0都遍历行列时间太慢额外数组本题O(mn)O(mn)两遍遍历空间稍大原地算法进阶O(mn)O(1)用第一行/列作为标记最优七、复杂度分析7.1 本题解法指标复杂度说明时间复杂度O(m * n)两次遍历矩阵空间复杂度O(m n)row 数组 m 个col 数组 n 个7.2 进阶原地算法指标复杂度说明时间复杂度O(m * n)三次遍历矩阵空间复杂度O(1)只用几个布尔变量八、面试追问问题回答要点为什么需要两次遍历第一次标记记录哪些行/列要置零第二次执行置零。如果边标记边置零会导致后续判断出错row[i]空间复杂度能进一步优化吗可以用矩阵第一行和第一列作为标记数组实现 O(1) 空间原地算法中 firstRowZero 的作用记录第一行本身是否需要置零因为第一行会被用作标记不能直接置零为什么原地算法要跳过第一行第一列第一行和第一列被用作标记数组如果对它们执行置零操作会丢失标记信息原地算法如何恢复第一行第一列最后根据 firstRowZero 和 firstColZero 单独处理第一行和第一列这个题有没有其他解法还有一种方案是设置一个 sentinel 值如 INFINITY来标记但会改变矩阵范围外的状态不推荐九、相关题目题号题目关键点73矩阵置零本题48旋转图像矩阵旋转54螺旋矩阵矩阵遍历59螺旋矩阵 II矩阵生成289生命游戏原地算法用位操作标记

相关文章:

【力扣100题】22. 矩阵置零

一、题目描述 给定一个 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: …...

日本电子产业转型启示:从技术过剩到商业模式创新

1. 日本电子产业的十字路口:一场箱根闭门会背后的行业剧痛2013年的春天,当全球电子产业的聚光灯都打在硅谷和深圳时,日本箱根的一家温泉旅馆里,正进行着一场鲜为人知却意义深远的对话。索尼、瑞萨、NEC、日立、松下、富士通、Mega…...

AXI协议深度解析:从握手到低功耗,一次搞懂芯片内部数据流的那些“潜规则”

AXI协议深度解析:从握手到低功耗,一次搞懂芯片内部数据流的那些“潜规则” 在当今高性能计算和复杂SoC设计中,AXI协议已成为连接处理器、存储器和外设的黄金标准。但真正理解AXI的精髓,远不止于掌握基础操作——那些隐藏在规范字里…...

Excel数据同步ERP/CRM太麻烦?一个Python脚本搞定多系统自动填充(基于GoBot)

Excel数据同步ERP/CRM太麻烦?一个Python脚本搞定多系统自动填充(基于GoBot) 每次月底看着财务同事在ERP系统里逐条录入Excel数据,市场部同事又在CRM里重复同样的操作,这种低效场景你一定不陌生。数据在不同系统间的孤岛…...

告别桌面混乱!Ubuntu 16.04 多桌面+Terminator分屏,打造程序员高效工作流

Ubuntu 16.04多桌面与Terminator分屏:构建程序员的高效工作流 作为一名长期在Ubuntu环境下工作的开发者,我深刻体会到工作环境配置对效率的影响。桌面混乱、窗口堆叠、频繁切换不仅浪费时间,还会打断编程的"心流"状态。经过多次迭代…...

告别龟速下载!实测对比Axel、Aria2、mwget三大神器,教你选对多线程工具

三大命令行下载神器深度横评:Axel、Aria2与mwget的性能对决 当你在终端里反复输入wget或curl命令,盯着缓慢增长的进度条时,是否想过还有更高效的解决方案?本文将带你深入探索Axel、Aria2和mwget这三款命令行下载加速工具&#xff…...

MGRE实验报告

一.实验概述实验名称:MGRE实验实验目的:掌握 PPP 协议的 PAP/CHAP 认证与 HDLC 封装配置,理解不同广域网链路协议的工作机制与认证流程。实现 MGRE 环境(R1 为 Hub)与 GRE 环境的部署,理解点到多点 VPN 与点…...

DDR3内存训练(Training)完全解析:从原理到代码,深入浅出

DDR3内存训练(Training)完全解析:从原理到代码,深入浅出 目录 一、为什么需要内存训练? 二、DDR3训练的核心原理 三、训练流程详解:一场精密的三步仪式 四、代码实战:从初始化到训练完成...

C语言-指针二

一. 指针的操作int main() {int a 10 , b 20, c 30;int *p NULL, *q NULL;p &a;//对指针变量p本身进行修改b *p;//*p为右值表示对变量a的读取*p 60;//*p为左值表示通过指向的内存空间对变量a的写入p &c;//p指向的内存空间发生变化b *p;//对c的读取操作*p 70…...

iOS越狱防火墙ijfw:从网络流量监控到精细化应用管控实战

1. 项目概述与核心价值最近在折腾一个挺有意思的开源项目,叫ijfw,全称是iOS Jailbreak Firewall。顾名思义,这是一个专门为越狱后的iOS设备设计的防火墙工具。如果你和我一样,是个喜欢在iPhone上“折腾”的玩家,或者对…...

数据中心机架内互连新范式:为何PCIe正取代以太网与InfiniBand?

1. 数据中心互连的十字路口:为什么是PCIe?在数据中心这个庞大而精密的数字世界里,服务器、存储和网络设备之间的“对话”效率,直接决定了整个系统的性能上限。过去十几年,我们习惯了用以太网(Ethernet&…...

Windows下Python包管理权限踩坑实录:从WinError 5到WinError 32的完整解决流程

Windows下Python包管理权限问题深度解析:从WinError 5到WinError 32的实战指南 作为一名长期在Windows平台进行Python开发的工程师,我深刻理解文件权限问题带来的困扰。特别是当你在紧急项目交付前夜,突然遭遇PermissionError: [WinError 5]或…...

从五管OTA到两级运放:在Cadence IC617中如何规划你的设计指标与晶体管尺寸(gm/id方法详解)

从五管OTA到两级运放:gm/id设计方法在Cadence IC617中的策略性应用 在模拟集成电路设计中,运算放大器的设计始终是工程师面临的核心挑战之一。特别是当设计需求从简单的五管OTA扩展到更复杂的两级运放时,设计者需要处理的不仅仅是晶体管尺寸的…...

2026年医疗卫生/护理求职AI工具横评:白衣天使的求职神器大比拼

导语 2026年,医疗卫生行业依然是最具社会价值和就业稳定性的行业之一。随着中国老龄化加速,医护人员需求持续扩大,仅公立医院护士岗位需求量就突破200万。然而,医护求职并不轻松:编制紧张、规培政策复杂、职称考试压力…...

从零到一:在STM32F103上构建FatFs文件系统并驱动W25Q64 Flash

1. 硬件准备与环境搭建 在开始构建FatFs文件系统之前,我们需要先准备好硬件环境。我手头用的是STM32F103C8T6最小系统板,搭配一块W25Q64 Flash芯片。这块Flash芯片容量为8MB,通过SPI接口通信,正好适合用来做文件存储介质。 首先得…...

从癌症研究到企业风控:用Python实战Cox比例风险模型(附完整代码与数据)

从医学到商业:Python实战Cox风险模型的企业级应用 在医疗领域,我们关心患者存活时间;在商业世界,我们关注客户生命周期。看似迥异的场景背后,都隐藏着同一个数学工具的身影——Cox比例风险模型。这个诞生于1972年的生存…...

原神帧率解锁技术解析:三步突破60FPS限制的完整方案

原神帧率解锁技术解析:三步突破60FPS限制的完整方案 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 你是否曾为《原神》PC版的60FPS限制感到困扰?当你的高性能显卡…...

C++ 特殊成员函数详解:构造、析构、拷贝与移动

C 特殊成员函数详解:构造、析构、拷贝与移动 目录 概述基础成员函数 默认构造函数虚析构函数 拷贝操作 拷贝构造函数拷贝赋值运算符 移动操作(C11) 移动构造函数移动赋值运算符 常见问题解析 为什么拷贝参数是 const T&?为什…...

基于确定性脚本与LLM决策的AI多智能体自动化监控系统设计与实践

1. 项目概述:一个为AI多智能体协作而生的“自动化监工”如果你正在用OpenClaw这类框架玩多AI智能体协作,大概率会遇到一个头疼的问题:怎么知道这群“数字员工”到底在不在干活?谁在摸鱼?任务到底完成了没有&#xff1f…...

红米AX3000路由器SSH完整解锁终极指南:3步获取root权限

红米AX3000路由器SSH完整解锁终极指南:3步获取root权限 【免费下载链接】unlock-redmi-ax3000 Scripts for getting Redmi AX3000 (aka. AX6) SSH access. 项目地址: https://gitcode.com/gh_mirrors/un/unlock-redmi-ax3000 想要完全掌控你的红米AX3000路由…...

C#元组类型简介

元组是 C# 7.0 引入的轻量级数据结构,用于临时组合多个值,无需定义专门的类或结构。 元组是有序的数据结构,成员按声明/创建时的顺序排列。(这里的元组只指值元组)元组类型在C#7.0前是有一个专门的内置类型&#xff0c…...

开源自托管看板工具:基于Preact+Hono+SQLite的零云依赖方案

1. 项目概述:一个为自托管与AI协作而生的看板应用如果你正在寻找一个可以完全掌控在自己手里、没有订阅费用、又能无缝集成到你自己产品中的看板工具,那么clawnify/open-kanban这个项目值得你花时间深入研究。它不是一个玩具,而是一个生产就绪…...

Windows运行Android应用终极指南:APK Installer让你的电脑秒变安卓手机

Windows运行Android应用终极指南:APK Installer让你的电脑秒变安卓手机 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 在移动应用生态日益丰富的今天&…...

对lsof、tcpdump、strace命令的简单记录

1. lsof (List Open Files) —— “谁占用了资源?” 核心哲学:Linux 中一切皆文件(包括磁盘文件、网络 Socket、设备)。 常用操作:lsof -i :15000:查看指定端口的进程占用及连接状态(LISTEN/EST…...

【紧急更新】Google官方刚推送的Veo 2 v2.3.1补丁深度解析:新增胶片扫描模拟、物理光晕建模与导演模式(Director Mode)

更多请点击: https://intelliparadigm.com 第一章:Google Veo 2 v2.3.1补丁核心特性概览 Google Veo 2 v2.3.1 补丁是面向视频生成模型推理优化与安全增强的关键更新,聚焦于低延迟部署、多模态对齐稳定性及合规性强化。该版本并非架构重构&a…...

基于 JiuwenClaw AgentTeam 集群模式的年会策划实战:从源码部署到多智能体协作落地

目录 摘要 一、引言:JiuwenClaw AgentTeam 让复杂任务迎刃而解 1.1 为什么选择年会策划作为 AgentTeam 实战场景 1.2 本文实战目标 二、JiuwenClaw 概述 2.1 JiuwenClaw 的核心特性 2.2 JiuwenClaw 的系统架构 2.3 JiuwenClaw 的三种运行模式 2.3.1 规划模…...

ElevenLabs API实战速成:从零部署高保真语音克隆服务,5步完成企业级TTS集成(含实时情感控制代码)

更多请点击: https://intelliparadigm.com 第一章:ElevenLabs超写实语音生成教程 ElevenLabs 是当前业界领先的 AI 语音合成平台,其模型在语调自然度、情感表达力与跨语言一致性方面表现卓越。本章将指导你完成从 API 接入到高质量语音生成的…...

WarcraftHelper:3步解决魔兽争霸3卡顿与兼容性问题终极指南

WarcraftHelper:3步解决魔兽争霸3卡顿与兼容性问题终极指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 你是否还在为魔兽争霸3在现代电…...

WPF中OxyPlot不同图表的使用

在 WPF 中使用 OxyPlot 实现不同图表,核心在于创建和配置PlotModel对象,并将其绑定到PlotView控件上进行显示。通过向PlotModel中添加不同类型的Series(数据系列),即可轻松实现折线图、柱状图、饼图、散点图等多种图表…...

CPT Markets:国际监管框架下的稳健运营

在评估金融服务平台时,监管合规、技术能力、客户服务等维度构成了重要的观察方向。CPT Markets作为业内较为活跃的服务机构,其在这些方面的实践具有一定的参考价值。本文将围绕评测视角,对其综合表现进行系统性的呈现,希望为读者提…...