[路飞]_课程表

164 阅读3分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

207. 课程表

题目

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 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 。这是不可能的。

题解

BFS

假设 prerequisites = [[5,8],[3,5],[1,9],[0,2],[4,5],[7,8],[4,9]]

解释:

  • 学习 5 之前,需要完成课程 8
  • 学习 3 之前,需要完成课程 5
  • 学习 1 之前,需要完成课程 9
  • 学习 0 之前,需要完成课程 2
  • 学习 4 之前,需要完成课程 5
  • 学习 7 之前,需要完成课程 8
  • 学习 4 之前,需要完成课程 9

课程之间的关系大概如下图所示:

graph LR
8 --> 5 & 7 --> 3 & 4 
9 --> 4 & 1
2 --> 0

解决这类有向图问题可以考虑一下从出度入度方面考虑;

课程012345789
入度110231100
  • 观察上表发现,凡是入度为0的,可以直接学习,比如课程2,8,9,其他课程暂时不能学;根据表格入度为0的课程开始学习;
  • 将可以入度为0的课程放入队列stack = [2,8,9]
  • 学习课程2;学完课程2,通过prerequisites发现,课程0入度需要减1;更新课程队列stack = [8,9,0]
  • 此时可以学习课程8,通过prerequisites发现可以将课程5,7的课程入度-1;更新课程队列stack = [9,0,5,7]
  • 此时可以学习课程9,通过prerequisites发现可以将课程1,4的课程入度-1;只有课程1的入度这时为0,课程队列stack = [0,5,7,1]
  • ...
  • 最后所有的课程又可以完成返回true

根据上述思路编辑代码如下:

代码

var canFinish = function (numCourses, prerequisites) {
  const len = prerequisites.length;

  // 出度,入度 的数组,数组表示当前课程的入度;入度为0,才可以学习;
  const outAndIn = Array(numCourses).fill(0);
  // 记录课程学完后,将课程相关的入度减小
  const keyValue = {};
  for (let i = 0; i < len; i++) {
    const [a, b] = prerequisites[i];
    outAndIn[a]++;
    if (keyValue[b]) {
      keyValue[b].push(a);
    } else {
      keyValue[b] = [a];
    }
  }

  // 先找到课程入度为0的课
  const stack = [];
  for (let i = 0; i < outAndIn.length; i++) {
    if (outAndIn[i] === 0) stack.push(i);
  }

  let count = 0;
  while (stack.length) {
    count++;
    const t = stack.pop();
    const next = keyValue[t];
    if (next && next.length > 0) {
      for (let i = 0; i < next.length; i++) {
        outAndIn[next[i]] -= 1;
        if (outAndIn[next[i]] === 0) {
          stack.push(next[i]);
        }
      }
    }
  }
  return count === numCourses;
};

var numCourses = 3,
  prerequisites = [
    [1, 0],
    [1, 2],
  ];
const aa = canFinish(numCourses, prerequisites);
console.log(aa);