返回
课程表 II:完成学习计划的最佳路径
前端
2024-01-06 19:57:29
序言
在知识的海洋中扬帆起航,我们时常会面临课程选择的难题。为了合理规划学习顺序,优化知识获取效率,掌握课程表的编制技巧至关重要。本文将深入剖析 LeetCode 210 题中的经典算法——课程表 II,带领你踏上制定最佳学习计划的探索之旅。
算法分析
关键概念:
- 有向无环图 (DAG): 一种只能按一个方向行进的图形,没有闭合路径。
- 拓扑排序: DAG 中顶点的顺序排列,其中每个顶点都排在所有指向它的顶点之后。
算法步骤:
- 构造邻接表: 将课程依赖关系表示为邻接表,其中每个顶点代表一门课程,边代表课程之间的依赖关系。
- 计算入度: 对于每个顶点,计算其入度,即指向它的边数。
- 拓扑排序: 从入度为 0 的顶点开始,依次执行以下步骤:
- 将顶点从队列中移除。
- 对于指向该顶点的每个邻接顶点,将其入度减 1。
- 如果邻接顶点入度为 0,将其添加到队列中。
- 检查是否完成拓扑排序: 如果队列不为空,则无法完成拓扑排序,说明存在循环依赖关系。
- 输出拓扑排序结果: 拓扑排序结果即为最佳学习顺序。
代码实现
def findOrder(numCourses: int, prerequisites: List[List[int]]) -> List[int]:
# 构造邻接表
graph = defaultdict(list)
for course, prereq in prerequisites:
graph[prereq].append(course)
# 计算入度
in_degrees = [0] * numCourses
for course in graph:
for prereq in graph[course]:
in_degrees[prereq] += 1
# 拓扑排序
queue = [course for course in range(numCourses) if in_degrees[course] == 0]
result = []
while queue:
course = queue.pop(0)
result.append(course)
for next_course in graph[course]:
in_degrees[next_course] -= 1
if in_degrees[next_course] == 0:
queue.append(next_course)
# 检查是否完成拓扑排序
if len(result) == numCourses:
return result
else:
return []
实战演练
假设我们有 4 门课程,课程依赖关系如下:
0 -> 1
1 -> 2
2 -> 0
应用课程表 II 算法:
- 构造邻接表:
graph = {
0: [1],
1: [2],
2: [0],
}
- 计算入度:
in_degrees = [1, 1, 1]
- 拓扑排序:
queue = [0]
result = []
while queue:
course = queue.pop(0)
result.append(course)
for next_course in graph[course]:
in_degrees[next_course] -= 1
if in_degrees[next_course] == 0:
queue.append(next_course)
- 输出结果:
result = [0, 1, 2]
由此可见,最佳学习顺序为 0 -> 1 -> 2。
进阶应用
课程表 II 算法不仅适用于传统意义上的课程学习,还可以扩展应用于各种需要合理规划顺序的任务中,例如:
- 软件开发中的依赖关系管理
- 项目管理中的任务调度
- 物流中的配送路线规划
结语
掌握课程表 II 算法,如同获取了一把知识海洋中的导航罗盘,助你合理规划学习顺序,高效获取知识。算法的精妙之处在于将有向无环图的拓扑排序技术与实际问题相结合,堪称知识编排与策略执行的典范。愿这篇文章成为你探索更广阔知识领域的踏脚石。