算法列表

207.课程表 中等

布莱克2026-03-25 16:53

问题:

你这个学期必须选修 numCourses 门课程,记为 0numCourses - 1

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai必须 先学习课程  bi

  • 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1

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

示例 1:

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

示例 2:

输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
输出:false
解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。

回答:

检测有没有环,如果两个课程之间相互依赖,比如1依赖0,0依赖1,则无法完成学习

把每门课程看作图中的一个节点,先修关系 [a, b] 表示 b → a 的有向边

构建数组,存放每门课程的前置依赖数量(入度)

构建队列,入度为0的课程放进队列,依次学习,每学完一门课程,把他的入度减1,入度为0时,把它推入队列可以进行学习,最终检测学完的数量是否等于课程的数量

//检测有没有环,有没有课程之间是相互依赖的
var canFinish = function(numCourses, prerequisites) {
    //课程的依赖关系
    let courseList = Array.from({length: numCourses}, () => []);
    //每个课程的前置依赖数量
    let indegree = new Array(numCourses).fill(0);
    for (let [course, prev] of prerequisites) {
        courseList[prev].push(course);
        indegree[course]++;
    }
    //没有前置依赖的课程
    let queue = [];
    for (let i = 0; i < numCourses; i++) {
        if (indegree[i] == 0) {
            queue.push(i)
        }
    }
    let learned = 0;
    while (queue.length) {
        let course = queue.shift();
        learned++;
        //检查接下来可以学习什么课
        for (let nextCourse of courseList[course]) {
            indegree[nextCourse]--;
            if (indegree[nextCourse] == 0) {
                queue.push(nextCourse)
            }
        }
    }
    return learned == numCourses
};


assistant