Hot 100 ---腐烂的橘子
本文概览本文以LeetCode题目腐烂的橘子为例讲解多源BFS的思路——所有腐烂橘子同时扩散每轮加1分钟最后用新鲜橘子计数判断是否全部腐烂一、题目二、题目分析题目要求每分钟腐烂的橘子会腐蚀上下左右相邻的新鲜橘子求全部橘子腐烂的最小时间。如果有橘子永远无法被腐蚀返回 -1核心特征腐烂橘子每分钟向四周扩散一圈这和上一篇岛屿数量的 BFS 是同一套框架——从起点向外一层层扩散。但有一个关键区别岛屿数量用 DFS 或 BFS 都行因为只要标记掉同一个岛屿的所有陆地即可不关心顺序而腐烂的橘子只能用 BFS因为需要计算时间只有 BFS 的层序遍历才能保证同一轮扩散的橘子属于同一分钟岛屿数量腐烂的橘子可用方法DFS 或 BFS只能 BFS起点遇到一个 ‘1’ 开始所有腐烂橘子同时开始扩散目标标记同一个岛屿的陆地腐蚀相邻的新鲜橘子统计count岛屿数量minutes轮数 分钟数无解情况无有新鲜橘子永远无法被腐蚀关键点腐烂橘子可能有多个它们同时扩散所以一开始就要把所有腐烂橘子全部加入队列思路概览classSolution{// 上下左右privatefinalint[][]dirs{{1,0},{-1,0},{0,-1},{0,1}};publicintorangesRotting(int[][]grid){if(gridnull||grid.length0)return0;// 长宽introwsgrid.length;intcolsgrid[0].length;// 好橘子数intfresh0;// 队列Queueint[]queuenewLinkedList();// 加入所有腐烂的橘子for(inti0;irows;i){for(intj0;jcols;j){// 如果是腐烂的橘子if(grid[i][j]2){queue.add(newint[]{i,j});}// 如果是好橘子elseif(grid[i][j]1){fresh;}}}// 如果没有好橘子if(fresh0)return0;// 如果有好橘子,开始腐烂returnbfs(grid,queue,rows,cols,fresh);}privateintbfs(int[][]grid,Queueint[]queue,introws,intcols,intfresh){intminutes-1;while(!queue.isEmpty()){intsizequeue.size();// 遍历当前队列中的所有腐烂橘子for(inti0;isize;i){int[]pointqueue.poll();// 遍历四个方向for(int[]dir:dirs){intxpoint[0]dir[0];intypoint[1]dir[1];// 如果越界或者不是好橘子,跳过if(x0||xrows||y0||ycols||grid[x][y]!1){continue;}// 腐烂橘子grid[x][y]2;// 好橘子数减一fresh--;// 加入队列queue.add(newint[]{x,y});}}// 分钟数加一minutes;}// 如果还有好橘子,返回-1if(fresh0){return-1;}returnminutes;}}思路简要说明多源 BFS先遍历整个网格把所有腐烂橘子的位置加入队列同时记录新鲜橘子的数量。这些腐烂橘子就是 BFS 的初始起点每轮 1 分钟用size记录当前队列长度一轮处理完当前所有腐烂橘子minutes1。这和层序遍历取每层节点数是一个道理fresh 计数每腐蚀一个新鲜橘子fresh-1。BFS 结束后如果 fresh 0说明有橘子永远没被腐蚀到返回 -1三、思路详解第一步为什么是多源 BFS普通 BFS 是从一个起点开始扩散。但这题的腐烂橘子可能有多个而且它们同时向四周扩散。如果对每个腐烂橘子单独做 BFS时间会出错——因为多个橘子是并行的不是串行的解决办法把所有腐烂橘子一开始就全部加入队列。这样第一轮处理的就是所有初始腐烂橘子第二轮处理的是它们腐蚀的新橘子第三轮处理的是新橘子腐蚀的更新橘子……每一轮就是 1 分钟初始 第1分钟 第2分钟 2 1 1 2 2 1 2 2 2 1 1 0 2 1 0 2 2 0 0 1 1 0 1 1 0 1 1 两个腐烂橘子 四个腐烂橘子 五个腐烂橘子 同时扩散 各腐蚀了一圈 继续扩散如果分开做 BFS 再取最大值逻辑会复杂很多。多源 BFS 让所有腐烂橘子在同一个队列里轮转天然实现了同时扩散第二步为什么要记录新鲜橘子数量这题有个特殊情况有些新鲜橘子可能永远不会被腐蚀。比如2 1 1 0 0 0 1 1 1上面两行的橘子可以被腐蚀但下面那行的橘子和上面的腐烂橘子隔了一层空格0永远接触不到所以永远不会腐烂如果我们只做 BFSBFS 结束后就不知道还有没有新鲜橘子剩着。所以一开始就要记录新鲜橘子的总数fresh每腐蚀一个就fresh--。BFS 结束后检查fresh 0如果是说明有橘子没被腐蚀到返回 -1第三步minutes 为什么初始为 -1intminutes-1;while(!queue.isEmpty()){intsizequeue.size();for(inti0;isize;i){// ...处理当前轮}minutes;}关键在于理解每一轮 while 循环代表什么初始队列里是所有初始腐烂的橘子它们还没开始扩散此时是第 0 分钟第一轮初始腐烂橘子向四周扩散腐蚀了第一批新鲜橘子。这批橘子是在第 1 分钟才腐烂的。minutes→ 0第二轮第一批新腐烂橘子继续扩散。minutes→ 1…那 minutes0 时明明已经腐蚀了第一批为什么不是 1因为最后一轮会有一个空轮——最后一批腐烂的橘子入队后它们周围已经没有新鲜橘子了但仍然会进入 while 循环处理一遍minutes多加了一次所以 -1 的初始值就是为了抵消这个空轮实际扩散了 N 轮while 循环跑了 N1 次最后一次是空的minutes -1 (N1) N正好是总分钟数第四步完整执行过程图解以这个网格为例2 1 1 1 1 0 0 1 1初始遍历腐烂橘子(0,0) 新鲜橘子数fresh 6 队列[(0,0)]第 1 轮处理队列中的 1 个橘子出队 (0,0)检查上下左右 下 (1,0) 是 1 → 腐烂fresh5入队 右 (0,1) 是 1 → 腐烂fresh4入队 网格变化 2 2 1 2 1 0 0 1 1 队列[(1,0), (0,1)] minutes 0第 2 轮处理队列中的 2 个橘子出队 (1,0)检查上下左右 右 (1,1) 是 1 → 腐烂fresh3入队 上 (0,0) 是 2 → 跳过 下 (0,1) 是 0 → 跳过 出队 (0,1)检查上下左右 右 (0,2) 是 1 → 腐烂fresh2入队 下 (1,1) 是 2 → 跳过刚被腐蚀 左 (0,0) 是 2 → 跳过 网格变化 2 2 2 2 2 0 0 1 1 队列[(1,1), (0,2)] minutes 1第 3 轮处理队列中的 2 个橘子出队 (1,1)检查上下左右 下 (2,1) 是 1 → 腐烂fresh1入队 其他方向是 0 或 2 → 跳过 出队 (0,2)检查上下左右 下 (1,2) 是 0 → 跳过 其他方向越界或 2 → 跳过 网格变化 2 2 2 2 2 0 0 2 1 队列[(2,1)] minutes 2第 4 轮处理队列中的 1 个橘子出队 (2,1)检查上下左右 右 (2,2) 是 1 → 腐烂fresh0入队 其他方向是 0 或 2 → 跳过 网格变化 2 2 2 2 2 0 0 2 2 队列[(2,2)] minutes 3第 5 轮处理队列中的 1 个橘子出队 (2,2)检查上下左右 全部越界或 0 或 2 → 无新增 队列为空 minutes 4最终检查fresh 0所有橘子都腐烂了返回 minutes 4第五步和岛屿数量 BFS 的对比这两题的 BFS 框架几乎一样关键区别在初始条件和统计目标岛屿数量腐烂的橘子初始队列遍历时遇到一个 ‘1’ 才入队先遍历一遍所有腐烂橘子全部入队BFS 调用次数每个岛屿调用一次只调用一次size 的作用取每层最后一个节点控制每轮处理几个橘子轮数的意义不关心轮数每轮 1 分钟标记方式改成 ‘0’改成 ‘2’腐烂结束后判断不需要检查 fresh 0核心都是 BFS 层序遍历的框架只是源从一个变成多个以及统计目标不同复杂度分析时间复杂度O(rows×cols)每个格子最多入队一次空间复杂度O(rows×cols)队列最坏情况存放所有格子

相关新闻

电吹风EMC-辐射 传导测试要求

电吹风EMC-辐射 传导测试要求

电吹风属于家用电器/个人护理电器,EMC 发射测试(辐射 RE 传导 CE)主要按 CISPR 14-1 / EN 55014-1(欧盟)、GB 4343.1-2024(中国 CCC,2026-06-01 强制实施)、FCC Part 15B&#xff0…

2026/9/29 10:55:19 阅读更多 →
神经网络架构搜索(NAS)原理与实践指南

神经网络架构搜索(NAS)原理与实践指南

1. 神经网络搜索(NAS)基础概念解析神经网络架构搜索(Neural Architecture Search, NAS)是近年来机器学习领域的重要突破方向。简单来说,它就像是为AI设计了一个"AI设计师",让算法能够自动寻找最适…

2026/9/28 12:37:49 阅读更多 →
二次元游戏出海技术架构:从卡池流水分析到多区域部署实战

二次元游戏出海技术架构:从卡池流水分析到多区域部署实战

(异环)1.2版本异环&真红国际服卡池流水表现分析:多市场数据解读与二次元游戏出海策略思考 最近《异环》1.2版本"异环&真红"卡池的全球流水数据在玩家社区引发了热烈讨论。作为一款备受关注的二次元手游&…

2026/10/12 9:38:50 阅读更多 →

最新新闻

如何让手机访问Symfony WebServerBundle本地服务器:0.0.0.0绑定与局域网暴露完整指南

如何让手机访问Symfony WebServerBundle本地服务器:0.0.0.0绑定与局域网暴露完整指南

【免费下载链接】web-server-bundle Provides commands for running applications using the PHP built-in web server 项目地址: https://gitcode.com/gh_mirrors/we/web-server-bundle 点击查看 免费下载 想让手机直接打开你电脑上跑的 Symfony 应用吗&#xff1…

2026/10/14 0:16:46 阅读更多 →
极大极小值算法与Alpha-Beta剪枝:棋类博弈搜索核心解析

极大极小值算法与Alpha-Beta剪枝:棋类博弈搜索核心解析

写一个会下棋的 AI 难吗?如果只靠暴力枚举,哪怕是一盘井字棋,顶多 9! 种走法还能忍,换到五子棋、国际象棋,分支因子一下子爆炸,普通程序根本算不完。这时候就得回到博弈树搜索的老套路:极大极小…

2026/10/14 0:16:46 阅读更多 →
Chan-Vese 图像分割算法 Python 实现与参数调优实战

Chan-Vese 图像分割算法 Python 实现与参数调优实战

简介:这份资源提供Chan-Vese图像分割算法的Python实现代码,面向正在学习图像处理、计算机视觉或活动轮廓模型的学生与开发者。Chan-Vese模型是首个完全脱离图像梯度信息、依靠区域信息构建能量函数的活动轮廓模型,为后续分割方法开辟了新方向…

2026/10/14 0:16:46 阅读更多 →
Neo4j 5.23 Windows 配置避坑指南:从安装到生产就绪

Neo4j 5.23 Windows 配置避坑指南:从安装到生产就绪

简介:Neo4j Community Edition 5.23.0 Windows版安装包,面向图形数据库初学者、高校学生及中小型项目开发者,提供开箱即用的本地图数据库环境,适用于社交关系分析、推荐系统原型开发、知识图谱构建等高度关联性数据场景。压缩包共…

2026/10/14 0:16:46 阅读更多 →
noto-fonts NEWS 解读:Noto 字体三次关键演进、upem 网格限制与 OFL 1.1 授权切换

noto-fonts NEWS 解读:Noto 字体三次关键演进、upem 网格限制与 OFL 1.1 授权切换

数据集 【免费下载链接】noto-fonts Noto fonts, except for CJK and emoji 项目地址: https://gitcode.com/gh_mirrors/no/noto-fonts 点击查看 免费下载 本文基于 noto-fonts 仓库根目录下的 NEWS.md 编写,梳理 2015—2018 年间 Noto 字体项目的三次里…

2026/10/14 0:16:46 阅读更多 →
glibc内存管理核心:malloc/free原理、RSS异常排查与调优实践

glibc内存管理核心:malloc/free原理、RSS异常排查与调优实践

搞了十多年Linux服务端,我遇到过不少内存方面的疑难杂症:程序跑着跑着RSS飙到十几个GB,看代码却找不到任何泄漏;压力测试一过进程就被OOM干掉;线上明明有内存空闲,服务却越跑越慢。这些问题表面上是业务逻辑…

2026/10/14 0:15:46 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →