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

LeetCode 207|课程表(Course Schedule)题解 – 拓扑排序判环法

题目描述

本题是一道典型的课程安排问题,题目大意如下:

你这个学期必须选修numCourses门课程,记为0numCourses - 1
某些课程有先修课程要求,先修课程以数组prerequisites给出,其中prerequisites[i] = [a_i, b_i]表示:

想学习课程a_i,你必须先完成课程b_i

请你判断是否可能完成所有课程的学习。如果可以,返回true;否则返回false

示例 1:

输入:numCourses = 2, prerequisites = [[1,0]] 输出:true 解释:总共有 2 门课程,学习课程 1 之前,需要先完成课程 0。

示例 2:

输入:numCourses = 2, prerequisites = [[1,0],[0,1]] 输出:false 解释:总共有 2 门课程,但课程 0 和课程 1 互为先修,形成环。

提示:

  • 1 <= numCourses <= 2000

  • 0 <= prerequisites.length <= 5000

  • prerequisites[i].length == 2

  • 0 <= a_i, b_i < numCourses

  • prerequisites 中的课程对互不相同


解题分析

1. 抽象为有向图判环问题

  • 每门课程可以视作图中的节点

  • 每个先修关系[a, b]可以视作一条有向边b -> a

  • 题目实质:判断课程依赖图是否有环

关键结论:

  • 图中存在环 → 不可能完成所有课程

  • 图中无环 → 可以完成所有课程


2. 拓扑排序(BFS)解法

核心思路:

  1. 建立邻接表表示图

  2. 统计每个节点的入度(还有多少前置课程未学)

  3. 将入度为 0 的节点入队

  4. BFS 遍历:

    • 出队节点表示已经学完

    • 对它的邻接节点,入度减 1

    • 如果邻接节点入度变为 0,入队

  5. 最后判断是否所有节点都被处理

优点:

  • 时间复杂度 O(V + E)

  • 空间复杂度 O(V + E)

  • 思路清晰,易于理解


3. C 语言实现

#include <stdlib.h> #include <stdbool.h> bool canFinish(int numCourses, int** prerequisites, int prerequisitesSize, int* prerequisitesColSize) { // 邻接表 int** graph = (int**)malloc(sizeof(int*) * numCourses); int* graphColSize = (int*)calloc(numCourses, sizeof(int)); // 入度数组 int* indegree = (int*)calloc(numCourses, sizeof(int)); // 初始化邻接表空间 for (int i = 0; i < numCourses; i++) { graph[i] = (int*)malloc(sizeof(int) * prerequisitesSize); } // 建图 + 统计入度 for (int i = 0; i < prerequisitesSize; i++) { int a = prerequisites[i][0]; int b = prerequisites[i][1]; graph[b][graphColSize[b]++] = a; indegree[a]++; } // 队列 int* queue = (int*)malloc(sizeof(int) * numCourses); int front = 0, rear = 0; // 入度为 0 的课程入队 for (int i = 0; i < numCourses; i++) { if (indegree[i] == 0) { queue[rear++] = i; } } int count = 0; // BFS 遍历 while (front < rear) { int cur = queue[front++]; count++; for (int i = 0; i < graphColSize[cur]; i++) { int next = graph[cur][i]; indegree[next]--; if (indegree[next] == 0) { queue[rear++] = next; } } } // 判断是否所有课程都能完成 return count == numCourses; }

4. 复杂度分析

项目复杂度
时间O(V + E)
空间O(V + E)
  • V = 课程数numCourses

  • E = 先修课程对数prerequisitesSize


5. 拓展思路

  1. DFS 判环法

    • 对每个节点进行 DFS,标记访问状态:

      • 0:未访问

      • 1:访问中(递归栈)

      • 2:已访问完成

    • 如果 DFS 过程中遇到状态为 1 的节点 → 存在环 → 返回 false

  2. 实际应用场景

    • 大学课程规划

    • 软件包依赖关系解析

    • 项目任务调度


6. 总结

  • 本题核心是判断有向图是否有环

  • BFS(拓扑排序)和 DFS(递归判环)都是高频面试解法

  • 面试中可以结合题目要求灵活选择

拓扑排序是图论入门的重要算法,理解它对于课程表、任务调度、依赖关系等问题都非常有帮助。


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

相关文章:

  • Qwen3.5-2B部署教程:WSL2环境下Windows用户一键运行图文模型
  • VSCode下载与配置Starry Night Art Gallery开发环境
  • C++易搞混知识: 指针、引用与取地址运算符对比分析
  • 专家答辩:视频不再是监控:基于三维空间智能体的空间计算系统构建与应用
  • Qwen3-Embedding-4B新手指南:可视化界面,轻松玩转文本向量化
  • OpenClaw技能市场指南:为千问3.5-9B寻找合适的功能扩展
  • LeetCode 210 课程表 II | 拓扑排序详解(C语言实现)
  • Swoole 5.0适配踩坑实录,深度解析协程生命周期变更、内存管理新规与RPC协议不兼容问题
  • OpenClaw+Qwen3-14B内容工厂:自动生成技术博客与SEO优化
  • VibeVoice实时语音合成实战:25种音色一键切换,打造多语言语音助手
  • nanobot超轻量级AI助手部署实测:快速体验Qwen3-4B模型的智能回复
  • [具身智能-314]:大语言模型处理文本的全过程
  • 镜像视界VS 专家 :空间计算系统最刁钻10问 + 答案
  • 一键部署实时口罩检测-通用:基于Gradio的交互式Web界面快速上手
  • Lychee-Rerank安全加固指南:防止注入攻击与数据泄露
  • Fish-speech-1.5多语言支持实战:13种语言的语音合成技巧
  • 2026年12VDC通讯设备电磁开关/家电用电磁开关多家厂家对比分析 - 品牌宣传支持者
  • 镜像视界数字孪生空间系统:二轮追问反杀清单
  • 5分钟玩转像素语言·跨维传送门:腾讯混元引擎翻译工具实测
  • Ostrakon-VL 终端 Anaconda 虚拟环境管理:多项目 Python 依赖隔离指南
  • Chord实战:用视频分析工具制作智能安防系统,自动检测异常行为
  • 晶振到底是啥?为什么有26M/52M/25M/12M/32.768K?”一口气讲透(工程师秒懂版)
  • 2026年口碑好的汽车电磁开关/新能源电磁开关/通讯设备电磁开关主流厂家对比评测 - 品牌宣传支持者
  • KOOK艺术馆GPU优化:BF16精度下色彩饱和度保持与灰阶过渡实测
  • VibeVoice多场景应用案例:有声读物生成、无障碍阅读工具、IVR系统
  • 优选算法的层序之径:队列专题
  • OpenClaw技能组合方案:千问3.5-27B+OCR实现证件信息提取
  • Gemma-3-12b-it+OpenClaw内容处理:从资料收集到草稿生成全流程
  • YOLO12 WebUI边缘计算部署:低延迟实时检测方案
  • 2026年OptoCraft波前探测器选型推荐榜:Trim200离子束刻蚀机、Essent Optics分光光度计选择指南 - 优质品牌商家