1. 课程表问题背景解析
课程表问题(Course Schedule)是计算机科学中经典的图论应用场景,也是技术面试中的高频考题。这个问题模拟了大学生选课时可能遇到的先修课程限制场景:假设你需要选修n门课程,某些课程可能有先修要求(比如必须先修完课程A才能选修课程B)。题目要求判断是否可能存在一个合理的选课顺序,使得所有课程都能被完成。
这个问题在实际工程中有着广泛的应用场景:
- 软件构建系统中的依赖关系管理(如Maven/Gradle的依赖解析)
- 任务调度系统中的执行顺序安排
- 工作流引擎中的步骤顺序验证
- 生产制造中的工序安排
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题建模与算法选择
2.1 图论模型构建
我们可以将课程表问题抽象为有向图的拓扑排序问题:
- 每门课程代表图中的一个顶点
- 先修关系
[a,b]表示一条从b指向a的有向边(必须先修b才能修a) - 问题转化为:判断这个有向图是否存在拓扑排序
2.2 算法选择与比较
解决拓扑排序问题主要有两种经典算法:
-
Kahn算法(基于入度统计):
- 统计每个节点的入度
- 将入度为0的节点加入队列
- 依次处理队列中的节点,并更新相关节点的入度
- 如果最终所有节点都被处理,则存在拓扑排序
-
DFS算法(基于深度优先搜索):
- 对每个未访问节点执行DFS
- 维护访问状态(未访问/访问中/已访问)
- 如果在DFS过程中遇到"访问中"的节点,说明存在环
两种算法的时间复杂度都是O(V+E),其中V是顶点数,E是边数。Kahn算法通常更直观,而DFS算法可以更容易地输出具体的拓扑顺序。
3. Kahn算法详细实现
3.1 算法步骤详解
以下是基于Kahn算法的Python实现:
python复制from collections import deque
def canFinish(numCourses, prerequisites):
# 初始化邻接表和入度数组
adj = [[] for _ in range(numCourses)]
in_degree = [0] * numCourses
# 构建图结构
for dest, src
