[路飞]_leetcode-210-课程表 II

简介: leetcode-210-课程表 II

网络异常,图片无法展示
|


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


[题目地址][B站地址]


现在你总共有 numCourses 门课需要选,记为 0numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai必须 先选修 bi


  • 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1]


返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组


示例 1:


输入: numCourses = 2, prerequisites = [[1,0]]
输出: [0,1]
解释: 总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。
复制代码


示例 2:


输入: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
输出: [0,2,1,3]
解释: 总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3] 。
复制代码


示例 3:


输入: numCourses = 1, prerequisites = []
输出: [0]
复制代码


提示:


  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= numCourses * (numCourses - 1)
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • ai != bi
  • 所有[ai, bi]互不相同


解题思路


在本题中,我们可以将课程之间的关系抽象成图,每一门课程有几个选修课程,入度就是几。


那么没有依赖的先修课程的课程入度就是 0,我们应该先学入度为 0 的课程,当整个课程学完的时候,需要把依赖于它的课程的入度 -1,这样当某个课程的所有先修课程学完了,它的入度就变成了 0,这其实就是图的拓扑排序的过程。


如果你对拓扑排序还不了解的话,可以看我之前的你真的懂排序吗?这篇文章,这里我们不再重复讲了。


而那些存在互相为先修课程的课程对,会在图中形成环,它们的入度无法变成 0,所以拓扑排序无法处理到它们。


所以我们可以将本题中的课程关系抽象成图进行拓扑排序,拓扑排序的过程就是学习课程的过程。当拓扑排序完成,排序结果数组中就保存了我们一种可能的学习课程的顺序。此时判断该数组长度是否等于 numCourses,如果相等,则可以学完所有课程,返回排序后的结果数组,否则没法学完所有课程,返回空数组即可。


动画演示


网络异常,图片无法展示
|


代码实现


var findOrder = function (numCourses, prerequisites) {
  // 初始化 nums 数组记录每个课程的入度数量
  const nums = Array(numCourses).fill(0),
    // 初始化 map 数组记录课程间的依赖关系
    map = Array(numCourses)
  // 遍历输入数组,记录入度数量和课程间的依赖关系
  for (let i = 0; i < prerequisites.length; i++) {
    const [a, b] = prerequisites[i]
    nums[a]++
    if (map[b]) map[b].push(a)
    else map[b] = [a]
  }
  // 初始化结果数组,保存学习课程的顺序
  const res = [],
  // 初始化中间队列为空数组
  queue = []
  // 遍历 nums 数组,将入度为 0 的课程首先放入队列
  for (let i = 0; i < numCourses; i++) {
    if (nums[i] === 0) queue.push(i)
  }
  // 当队列不为空的时候
  while (queue.length) {
    // 弹出队首的元素
    const cur = queue.shift(),
    // 获取依赖当前课程的课程列表
    list = map[cur];
    // 将当前课程放入结果数组
    res.push(cur)
    // 如果有依赖当前课程的课程,将它们的入度 -1
    if (list) {
      for (let i = 0; i < list.length; i++) {
        nums[list[i]]--
        // 如果某个课程的入度为 0,将其放入队列
        if (nums[list[i]] === 0) queue.push(list[i])
      }
    }
  }
  // 如果学完课程的数量等于课程总数,返回学习课程的顺序,否则返回空数组
  return res.length === numCourses ? res : []
}
复制代码


至此我们就完成了 leetcode-210-课程表 II


如有任何问题或建议,欢迎留言讨论!👏🏻👏🏻👏🏻

相关文章
|
8月前
|
Go
golang力扣leetcode 207.课程表
golang力扣leetcode 207.课程表
84 0
|
8月前
|
人工智能 算法 BI
力扣1462.课程表
力扣1462.课程表
|
8月前
|
算法
力扣630.课程表
力扣630.课程表
|
8月前
|
人工智能 BI
leetcode-207:课程表
leetcode-207:课程表
51 0
|
8月前
leetcode-630:课程表 III
leetcode-630:课程表 III
50 0
|
8月前
|
存储 人工智能 BI
【力扣热题100】207. 课程表 python 拓扑排序
【力扣热题100】207. 课程表 python 拓扑排序
75 0
|
8月前
|
存储 人工智能 算法
☆打卡算法☆LeetCode 210. 课程表 II 算法解析
☆打卡算法☆LeetCode 210. 课程表 II 算法解析
|
8月前
|
存储 人工智能 算法
☆打卡算法☆LeetCode 207. 课程表 算法解析
☆打卡算法☆LeetCode 207. 课程表 算法解析
LeetCode-630 课程表Ⅲ
这里有 n 门不同的在线课程,按从 1 到 n 编号。给你一个数组 courses ,其中 courses[i] = [durationi, lastDayi] 表示第 i 门课将会 持续 上 durationi 天课,并且必须在不晚于 lastDayi 的时候完成。 你的学期从第 1 天开始。且不能同时修读两门及两门以上的课程。 返回你最多可以修读的课程数目。