【忍者算法】从扫雷游戏到矩阵操作:探索矩阵置零问题|LeetCode 73 矩阵置零
从扫雷游戏到矩阵操作:探索矩阵置零问题
生活中的算法
想象你在玩扫雷游戏,当你点到一个地雷时,不仅这个格子会被标记,与它同行同列的格子也都会受到影响。或者想象一个办公室的座位表,如果某个位置发现了感染者,为了安全起见,需要将该员工所在的整行(同排同事)和整列(对面同事)都标记为密切接触者需要检测。
这种"一点触发,全行全列响应"的场景在生活中很常见:
- 学校课程表中,如果某个老师请假,那一整行的课程都需要调整
- 表格处理软件中,调整某个单元格的格式,可以统一设置整行整列
- 影院选座系统中,如果一个座位损坏,可能需要锁定那一排和那一列的预订功能
问题描述
LeetCode第73题"矩阵置零"是这样描述的:给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
例如:
输入:matrix = [
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:[
[1,0,1],
[0,0,0],
[1,0,1]
]
最直观的解法:额外空间标记
就像在处理办公室防疫时,先用一张新表记录下所有需要检测的位置,然后统一处理。
让我们用一个简单的例子来理解:
原矩阵:
[1,2,0]
[3,4,5]
1. 记录0所在的位置:
- 第0行,第2列有个0
2. 标记需要置零的行和列:
- 需要置零的行:[0]
- 需要置零的列:[2]
3. 根据记录修改矩阵:
[0,0,0] // 第0行全置零
[3,4,0] // 第2列置零
优化解法:原地标记
仔细思考会发现,我们可以用矩阵的第一行和第一列来记录标记信息,就像用办公室的墙上的记事板来标记需要处理的区域。这样就不需要额外的空间了。
原地标记的原理
- 先记录第一行和第一列是否原本包含0
- 用第一行和第一列作为标记板
- 处理剩余的矩阵
- 最后根据第一步的记录处理第一行和第一列
示例演示
用下面的矩阵来说明:
[1,2,3]
[4,0,6]
[7,8,9]
1. 记录第一行和第一列的状态:
- 第一行没有0
- 第一列没有0
2. 用第一行和第一列标记:
- 因为matrix[1][1]=0,所以:
- 标记第一行:matrix[0][1]=0
- 标记第一列:matrix[1][0]=0
3. 根据标记处理矩阵主体:
[1,0,3]
[0,0,0]
[7,0,9]
4. 最后根据第一步的记录处理第一行第一列
Java代码实现
public void setZeroes(int[][] matrix) {
if (matrix == null || matrix.length == 0) return;
int m = matrix.length;
int n = matrix[0].length;
// 记录第一行和第一列是否原本包含0
boolean firstRowHasZero = false;
boolean firstColHasZero = false;
// 检查第一行
for (int j = 0; j < n; j++) {
if (matrix[0][j] == 0) {
firstRowHasZero = true;
break;
}
}
// 检查第一列
for (int i = 0; i < m; i++) {
if (matrix[i][0] == 0) {
firstColHasZero = true;
break;
}
}
// 使用第一行和第一列作为标记
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0; // 标记该行
matrix[0][j] = 0; // 标记该列
}
}
}
// 根据标记处理非第一行第一列的部分
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
// 处理第一行
if (firstRowHasZero) {
for (int j = 0; j < n; j++) {
matrix[0][j] = 0;
}
}
// 处理第一列
if (firstColHasZero) {
for (int i = 0; i < m; i++) {
matrix[i][0] = 0;
}
}
}
解法比较
让我们比较这两种方法:
额外空间标记:
- 时间复杂度:O(m×n)
- 空间复杂度:O(m+n)
- 优点:思路清晰,实现简单
- 缺点:需要额外空间
原地标记:
- 时间复杂度:O(m×n)
- 空间复杂度:O(1)
- 优点:不需要额外空间
- 缺点:实现稍复杂,需要额外记录第一行列的状态
解题技巧总结
这道题给我们的启发:
- 矩阵问题中,往往可以利用矩阵本身来存储信息
- 处理特殊情况(如第一行列)时,可以单独考虑
- 分步骤处理复杂问题可以让思路更清晰
- 在修改数据时,注意保护原始信息
类似的问题还有:
- 生命游戏
- 旋转图像
- 岛屿数量
小结
通过矩阵置零这道题,我们学会了如何巧妙地利用矩阵本身来存储信息,避免使用额外空间。这种思维方式不仅适用于本题,在处理需要原地修改数据的矩阵问题时都很有启发。记住,当遇到需要在矩阵中标记信息的问题时,考虑能否利用矩阵本身的某些位置来存储标记!
作者:忍者算法
公众号:忍者算法
我准备了一份刷题清单,以及这些题目的详细题解,覆盖了绝大部分常见面试题。我可以很负责任地说,只要你把这些题真正掌握了,80%的算法面试都能遇到相似题目。公众号回复【刷题清单】获取~
【忍者算法】从扫雷游戏到矩阵操作:探索矩阵置零问题|LeetCode 73 矩阵置零的更多相关文章
- C++算法代码——扫雷游戏
题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1685 题目描述 扫雷游戏是一款十分经典的单机小游戏. 在 n 行 m 列的雷区中有一 ...
- Java实现 LeetCode 73 矩阵置零
73. 矩阵置零 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0.请使用原地算法. 示例 1: 输入: [ [1,1,1], [1,0,1], [1,1,1] ...
- leetcode 73 矩阵置零 Python
矩阵置零 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0.请使用原地算法. 示例 1: 输入: [ [1,1,1], [1,0,1], [1 ...
- LeetCode 73. 矩阵置零(Set Matrix Zeroes)
题目描述 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0.请使用原地算法. 示例 1: 输入: [ [1,1,1], [1,0,1], [1,1,1 ...
- Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper)
Leetcode之广度优先搜索(BFS)专题-529. 扫雷游戏(Minesweeper) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ary Tre ...
- 【Android】自己动手做个扫雷游戏
1. 游戏规则 扫雷是玩法极其简单的小游戏,点击玩家认为不存在雷的区域,标记出全部地雷所在的区域,即可获得胜利.当点击不包含雷的块的时候,可能它底下存在一个数,也可能是一个空白块.当点击中有数字的块时 ...
- Java实现 蓝桥杯VIP 算法提高 扫雷
算法提高 扫雷 时间限制:1.0s 内存限制:256.0MB 问题描述 扫雷游戏你一定玩过吧!现在给你若干个n×m的地雷阵,请你计算出每个矩阵中每个单元格相邻单元格内地雷的个数,每个单元格最多有8个相 ...
- C#编写扫雷游戏
翻看了下以前大学学习的一些小项目,突然发现有个项目比较有意思,觉得有必要把它分享出来.当然现在看来,里面有很多的不足之处,但因博主现在已经工作,没有时间再去优化.这个项目就是利用C#编写一个Windo ...
- [Swift]LeetCode529. 扫雷游戏 | Minesweeper
Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix representin ...
- FZU OJ 1056 :扫雷游戏
Problem 1056 扫雷游戏 Accept: 2624 Submit: 6903Time Limit: 1000 mSec Memory Limit : 32768 KB Prob ...
随机推荐
- IT人写好简历的原则与方法
来源: 51cto 发布时间: 2010-03-19 14:49 阅读: 3270 次 推荐: 3 原文链接 [收藏] 时常,在各大论坛看到不少的朋友在张贴简历,希望得到他人的指点. ...
- springgateway 路由转发
有些情况下,我们希望不直接访问后端地址,这个时候可以通过springgateway网关进行处理.下面只是一个简单的例子. 至于URL,变化,我们可以通过编写程序逻辑来实现. 实现步骤: 1.新建项目 ...
- Element-UI 调整
1.对话框 当打开的对话框页面元素众多,俨然一个iframe页面时,可以做2个优化: 滚动条:对话框去滚动,当对话框内容过多时,把滚动条控制在对话框内部,避免出现页面级的滚动条 标题栏:优化对话框标题 ...
- S2P医药营销智能管理平台特点和优势
S2P医药营销智能管理平台是正也科技打造的一个专为医药行业设计的综合性营销解决方案,旨在通过智能化.数据驱动的方式提升医药企业的营销效率和效果.以下是关于S2P医药营销智能管理平台的一些主要特点和优势 ...
- uni-app小程序项目使用iconfont字体图标
前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验非常棒,公司项目就是主推uni-app. 为什么要这么做? 借 ...
- ng-alain: delon/abc/sc 简化容器
简化表单HTML模板的高阶组件,并进一步优化了一些细节: 更友好的表单校验状态 自动化响应式布局 自动维护表单 id 它由 se-container 容器(指令)和 se 组件来表示一个表单,一个简单 ...
- Qt音视频开发16-通用悬浮按钮工具栏的设计
一.前言 通用悬浮按钮工具栏这个功能经过了好几个版本的迭代,一开始设计的时候是写在视频控件widget窗体中,当时功能简单就放一排按钮在顶部悬浮widget中就好,随着用户需求的变化,用户需要自定义悬 ...
- Qt编写4K/8K大分辨率播放器(8K占用1%CPU)
一.前言 在经过多种内核的洗礼以后,逐渐对不同内核的不同音视频文件和视频流进行大量的对比测试,比如测试对各种格式的支持性,对各种网络流的支持程度,在同一个地址下占用的CPU/GPU资源比对,最终发现播 ...
- Qt音视频开发43-人脸识别服务端
一.前言 上一篇文章写道人脸识别客户端程序,当然要对应一个服务端程序,客户端才能正常运行,毕竟客户端程序需要与服务端程序进行交互他才能正常工作.通常人脸识别服务端程序需要和人脸识别的相关处理库在一起, ...
- 【量化读书笔记】【打开量化投资的黑箱】CH.04.风险模型
风险管理不仅仅是规避风险和减少损失,是通过对敞口实施有目的的选择和规模控制来提高收益的质量和稳定性. (注:敞口,一般指金融活动中存在金融风险的部位以及受金融风险影响的程度) 本质上风险模型是为阿尔法 ...