题目重点:Course Schedule变体先落在明确DAG训练合同,不推定额外条件。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 具体变体细则未明,训练count门课、(course,prerequisite)边,无学期容量/时长。
- 返回一种顺序;有环None、零课[]。不保证最小字典序。
解题路线
- 边pre→course,入度是未完成前置数。把所有入度0课入队,弹出后减少后继入度,变0入队。
- 若处理数等count则全部可完成;剩余非0说明存在环或依赖环的节点。重复边用set去重,防重复入度导致假环。
- 本题顺序不等于带持续时间的关键路径,也不等于每学期最多K门的最少学期数。扩展前确认额外资源、先修是否必须跨学期及目标。
手动走一遍
(1,0),(2,0)可[0,1,2]或[0,2,1]。(1,0),(0,1)返回None;不能把部分无关课的顺序当成功。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
from collections import deque
def order(count,prerequisites):
edges=[set() for _ in range(count)];degree=[0]*count
for course,pre in prerequisites:
if not (0<=course<count and 0<=pre<count):raise ValueError("unknown course")
if course not in edges[pre]:edges[pre].add(course);degree[course]+=1
queue=deque(i for i in range(count) if degree[i]==0);result=[]
while queue:
u=queue.popleft();result.append(u)
for v in edges[u]:
degree[v]-=1
if degree[v]==0:queue.append(v)
return result if len(result)==count else None
复杂度
O(V+E)时间/空间;要字典序最小用minheap使O((V+E)logV)保守。
易错点与追问
容易失分的边界
- 把(course,pre)当course→pre会反序。
- 所有节点初始入队会无视前置。
继续深挖
- 最少学期无限并行时如何用层数DP?
- 返回一条导致失败的环怎样加DFS状态与parent?
