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

BFS 经典双题:腐烂的橘子 + 课程表 | 拓扑排序入门必刷

目录

一、腐烂的橘子(中等)

题目描述

解题思路(多源 BFS)

完整代码

二、课程表(中等)

题目描述

解题思路(拓扑排序)

完整代码

核心考点总结


一、腐烂的橘子(中等)

题目描述

在给定的网格中,每个单元格可以有以下三个值之一:

  • 0表示空单元格
  • 1表示新鲜橘子
  • 2表示腐烂的橘子

每分钟,任何与腐烂橘子相邻(上、下、左、右)的新鲜橘子都会腐烂。返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回-1

解题思路(多源 BFS)

这是典型的多源 BFS问题:

  1. 初始化队列:先遍历网格,把所有腐烂的橘子(值为2)加入队列,同时统计新鲜橘子的数量。
  2. 分层 BFS:每一分钟处理队列中的所有腐烂橘子,把它们相邻的新鲜橘子腐烂,并加入队列。
  3. 判断结果:如果新鲜橘子全部腐烂,返回分钟数;否则返回-1

完整代码

java

运行

public class Solution { public int orangesRotting(int[][] grid) { int rows = grid.length; int cols = grid[0].length; Queue<int[]> queue = new LinkedList<>(); int freshCount = 0; int minutes = 0; // 1. 初始化队列和新鲜橘子计数 for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (grid[i][j] == 2) { queue.offer(new int[]{i, j}); } else if (grid[i][j] == 1) { freshCount++; } } } // 如果没有新鲜橘子,直接返回 0 if (freshCount == 0) return 0; // 方向数组:上、下、左、右 int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 2. BFS 分层处理 while (!queue.isEmpty()) { int size = queue.size(); for (int i = 0; i < size; i++) { int[] curr = queue.poll(); int x = curr[0], y = curr[1]; for (int[] dir : dirs) { int nx = x + dir[0]; int ny = y + dir[1]; if (nx >= 0 && nx < rows && ny >= 0 && ny < cols && grid[nx][ny] == 1) { grid[nx][ny] = 2; // 腐烂 freshCount--; queue.offer(new int[]{nx, ny}); } } } minutes++; } // 3. 判断是否还有新鲜橘子 return freshCount == 0 ? minutes - 1 : -1; } }

二、课程表(中等)

题目描述

你这个学期必须选修numCourses门课程,编号从0numCourses-1。某些课程有先修条件,例如,选修课程0之前,你需要先修课程1,用[0,1]表示。判断是否可能完成所有课程的学习。

解题思路(拓扑排序)

这是典型的有向无环图(DAG)拓扑排序问题:

  1. 构建邻接表和入度数组:用邻接表表示课程依赖关系,用入度数组统计每门课程的先修数。
  2. 初始化队列:把入度为 0 的课程(没有先修条件)加入队列。
  3. BFS 处理:每处理一门课程,把它的后继课程的入度减 1,如果入度变为 0,就加入队列。
  4. 判断结果:如果处理的课程数等于总课程数,说明可以完成;否则存在环,无法完成。

完整代码

java

运行

public class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { // 1. 构建邻接表和入度数组 List<List<Integer>> adj = new ArrayList<>(); int[] inDegree = new int[numCourses]; for (int i = 0; i < numCourses; i++) { adj.add(new ArrayList<>()); } for (int[] pre : prerequisites) { int course = pre[0]; int prereq = pre[1]; adj.get(prereq).add(course); inDegree[course]++; } // 2. 初始化队列,入度为 0 的课程入队 Queue<Integer> queue = new LinkedList<>(); for (int i = 0; i < numCourses; i++) { if (inDegree[i] == 0) { queue.offer(i); } } // 3. BFS 处理 int count = 0; while (!queue.isEmpty()) { int curr = queue.poll(); count++; for (int next : adj.get(curr)) { inDegree[next]--; if (inDegree[next] == 0) { queue.offer(next); } } } // 4. 判断是否可以完成所有课程 return count == numCourses; } }

核心考点总结

表格

题目核心算法关键技巧
腐烂的橘子多源 BFS初始化所有腐烂橘子为起点,分层处理
课程表拓扑排序(BFS)入度数组 + 邻接表,处理 DAG 依赖

这两道题是 BFS 在不同场景下的经典应用,掌握它们可以帮你快速理解多源 BFS 和拓扑排序的核心思想。

http://www.jsqmd.com/news/594029/

相关文章:

  • 别再只调参了!深入torchvision.datasets.CIFAR10源码,理解PyTorch数据加载的设计哲学
  • 2025届学术党必备的六大AI论文助手解析与推荐
  • Ubuntu 22.04下Milvus集群部署实战:从Docker提取二进制文件的完整指南
  • 基于Simulink的四自由度磁悬浮轴承控制仿真:电流环、位置环、位移解析及磁轴承模型PID控...
  • DSI3协议四大模式(CRM/PDCM/BDM/DM)全解析:从汽车胎压监测到电池管理,看它如何工作
  • 1Panel面板深度体验:比宝塔更轻量的Docker管理方案?CasaOS环境实测对比
  • 为什么要 TCP,IP 层实现控制不行么:从分层哲学到不可逾越的物理限制
  • 2026-4-5
  • Python办公自动化:3种Word转PDF方法实测(附代码对比)
  • 前端必懂:开发环境、构建打包的核心差异,新手再也不踩坑
  • 深度学习检测不准确智能电表案例研究代码功能说明
  • “16QAM调制与解调系统的SystemView仿真及分析”
  • HJ164 太阳系DISCO
  • 手把手教你开发电竞护航系统:从零到上线的小程序全流程
  • 【Matlab 六自由度机器人】从理论到实践:笛卡尔与关节空间规划在复杂避障场景下的MATLAB实现与对比
  • 5个技巧让你高效畅玩Switch游戏:开源Ryujinx模拟器全攻略
  • 永磁同步电机(PMSM)速度电流双闭环FOC矢量控制策略详解
  • 解决GLIBC版本冲突:手动编译libcrypto.so.1.0.0的完整指南
  • 保姆级教程:在CentOS 7.9上从源码编译安装nvtop 3.1.0(含CMake 3.29.7依赖安装)
  • 前端CSS精讲05:Grid网格布局——现代页面最强二维布局方案
  • 你的电脑配置,可能决定了Vivado升级时IP会不会“偷懒”:一次关于IP缓存与硬件资源的观察
  • Ubuntu 20.04忘记密码?5分钟搞定root和用户密码重置(附GRUB菜单截图)
  • Avalonia实战:5分钟搞定无边框窗口自定义(附拖拽功能完整代码)
  • 学生评教|高校评教|基于SpringBoot+vue高校学生评教系统 (源码+数据库+文档)
  • 离谱又惊艳!C++隐藏宝藏库numeric_range深度探索,竟藏着JS彩蛋和隐零点
  • 常见的 HTTP 状态码有哪些:从 1xx 到 5xx 全解及排错流程图
  • 五次多项式换道轨迹规划+MPC轨迹跟踪控制simulink模型(有说明文档) 版本
  • 开发实战:asp.net core + ef core 实现动态可扩展的分页方案
  • 电力电子新手必看:SPWM单极性倍频调制在Simulink中的实现与优化
  • 告别数据孤岛:手把手教你用ArcMap的Join功能,把Excel数据精准‘贴’到地图上