SWE · Coding

课程依赖:可完成判断与一种拓扑顺序

Course Schedule变体先落在明确DAG训练合同,不推定额外条件。

题目重点:Course Schedule变体先落在明确DAG训练合同,不推定额外条件。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 具体变体细则未明,训练count门课、(course,prerequisite)边,无学期容量/时长。
  • 返回一种顺序;有环None、零课[]。不保证最小字典序。

解题路线

  1. 边pre→course,入度是未完成前置数。把所有入度0课入队,弹出后减少后继入度,变0入队。
  2. 若处理数等count则全部可完成;剩余非0说明存在环或依赖环的节点。重复边用set去重,防重复入度导致假环。
  3. 本题顺序不等于带持续时间的关键路径,也不等于每学期最多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?
✓已复制微信号!