210. 课程表 II

现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 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]

思路

这道题和(连接)做法几乎一样,就是用拓扑排序。只不过这一题返回的不是True和False,而是课程顺序,反正按我们的方法这两种结果都有。直接复制那一题的思路了:

拓扑排序是一个图问题。我们把每一门课当成一个节点,把“学完课程a才能学课程b”模拟成a到b的一个有向连接。那么题目中给的条件就可以转化为一个有向图。

如何进行拓扑排序呢?我们每次只从图中取“不被任何节点指向”的“源头结点”,在这一题中也就是不需要任何先验课程的基础课。我们找到这一节点后,将它作为我们开始上的第一节课,并把它从表中删除。

随着源头结点的删除,就会释放出新的源头结点,我们再重复这样的操作。最终如果所有的节点都可以顺利删除,则我们的课程就可以顺利学完,删除的顺序也就是我们其中一个可行的学习路线;如果最终有部分节点无法删除(即谁都不是源头结点,互相指),则说明这是一个有环图,无法学完课程。

具体如何实现拓扑排序呢?我们通常使用邻接矩阵邻接表来表示节点之间的指向关系。

举个例子,假如有n个节点:

邻接矩阵是一个n*n的二维数组,假如节点1指向节点2和节点4,则数组[1][2]和数组[1][4]位置为1,其他位置为0;

邻接表则不耗费n*n的空间,我们只需要一个长度为n的数组,假设节点1指向节点2和节点4,数组[1]位置就存放一个指针,该指针指向具有结点2和节点4这两个元素的链表。

这道题我们使用邻接表即可。因为是用python来写,所以我们可以使用一个更为方便的数据结构代替链表,这个数据结构就是:集合。用集合来代替链表的功能,写出来就是这样:

除了邻接表外,我们还需要一个入度表,出度、入度也是图中非常基础的知识点了:对于一个节点,有几个节点指向它,它的入度就是几;它指向其他几个节点,它的出度就是几。我们需要一个入度表来寻找那些入度为0的点,从而根据拓扑排序逻辑将他们删除。

代码:

class Solution(object):def canFinish(self, numCourses, prerequisites):# 依赖的长度clen = len(prerequisites)if clen == 0:#没有课程依赖return True#肯定可以学完,直接返回True# 初始化入度数组,一开始全部为 0in_degrees = [0 for _ in range(numCourses)]# 初始化邻接表adj = [set() for _ in range(numCourses)]#adj = [set()]*numCourses这样写则错!这种可变的不能乘 就用for永远的神for second, first in prerequisites:#注意题目中给的顺序in_degrees[second] += 1#被指向的课程,入度+1adj[first].add(second)#节点first的邻接节点里加入second#现在入度表和邻接表都初始化好了# 首先定义一个队列,遍历一遍入度表,把所有入度为 0 的结点加入队列res=[]queue = []for i in range(numCourses):if in_degrees[i] == 0:#因为入度为0,所以queue.append(i)#加入队列中的节点(课程)都是可以直接学的counter = 0while queue:#当队列中有节点top = queue.pop(0)#取出(删除)节点res.append(top)#将目前学的课程加入res表for successor in adj[top]:#找到这个删除节点指向的节点们in_degrees[successor] -= 1#把这些节点们的入度-1if in_degrees[successor] == 0:#如果哪一个节点入度-1后入度为0queue.append(successor)#则它也可以直接学了,加入队列If len(res)== numCourses:#学的课程数等于总课程数,学完了return res#返回所学课程顺序return []

小结:

拓扑排序还是非常典型并且有用的算法(起码我觉得这一题比其他大多数算法能解决的问题更加贴近实际一点)。从中我们也可以复习图论的相关知识,是要掌握一下的。

LeetCode课程表Ⅱ相关推荐

  1. 搜索与图论1—深搜、宽搜、拓扑排序

    本人的LeetCode账号:魔术师的徒弟,欢迎关注获取每日一题题解,快来一起刷题呀~ 本人Gitee账号:路由器,欢迎关注获取博客内容源码. 文章目录 一.深度优先搜索 1 排列数字 2 N皇后 二. ...

  2. LeetCode 210. 课程表 II(拓扑排序)

    1. 题目 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课 ...

  3. LeetCode 207. 课程表(拓扑排序)

    1. 题目 你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 . 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个 ...

  4. LeetCode 807. 保持城市天际线 / 630. 课程表 III(贪心+优先队列)/ 851. 喧闹和富有(拓扑排序)

    807. 保持城市天际线 2021.12.13 每日一题 题目描述 给你一座由 n x n 个街区组成的城市,每个街区都包含一座立方体建筑.给你一个下标从 0 开始的 n x n 整数矩阵 grid ...

  5. Leetcode 207.课程表

    课程表 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总 ...

  6. leetcode 210. Course Schedule II | 210. 课程表 II(Java)

    题目 https://leetcode.com/problems/course-schedule-ii/ 题解 本题与 leetcode 207. Course Schedule 基本相同,代码只需要 ...

  7. leetcode 207. Course Schedule | 207. 课程表(Java)

    题目 https://leetcode.com/problems/course-schedule/ 题解 这的道题思路,来源于数据结构中的 拓扑排序 问题,主要思路是,通过逐步遍历删除入度为 0 的节 ...

  8. LeetCode—210. 课程表 II

    210. 课程表 II 题目描述:现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1.给你一个数组 prerequisites ,其中 prerequisite ...

  9. LeetCode—207. 课程表

    207. 课程表 题目描述:你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 . 在选修某些课程之前需要一些先修课程. 先修课程按数组 prerequisi ...

最新文章

  1. 我的博士之路(壮根美颜-康亚龙):五年读博路,苦熬曙光明
  2. 德国蓝皮书:解决特定问题 德国渐进建设智慧城市
  3. ASP.NET MVC中你必须知道的13个扩展点
  4. jmeter的xpath断言 [XPath Assertion]
  5. 计算机科学导论第二章,补基础:自学:计算机科学导论 第二章 数字系统
  6. php yii model,Yii模型
  7. c语言默认参数_5.1 C++有默认参数的函数
  8. oracle sequence last_number,关于oracle序列的LAST_NUMBER
  9. opensips mysql 认证_基于ubuntu中使用mysql实现opensips用户认证的解决方法
  10. python的for语句写新的字符串_Python:for循环遍历对象,而不是字符串
  11. Express框架是什么
  12. android获取键值对,Android应用开发android中的键值对实例讲解
  13. 鸢尾花(Iris)数据集下载保存到Excel文件
  14. Linux:CPU中断绑定----计算 SMP IRQ Affinity
  15. coldfusion_在Windows上安装和配置ColdFusion MX 6.1
  16. 什么是响应式布局?原理是什么?
  17. 云计算——Google云计算原理与应用(Google文件系统GFS)
  18. 阿里云服务器cnetos7常用命令
  19. 【学术交流】计算机国际会议中proceedings,conference,paper,workshop,demo的都是什么意思
  20. python爬虫爬取58同城租房信息(使用动态IP)输出Excel文件

热门文章

  1. java 插入 mysql 乱码_解决java中插入mysql中文乱码的方法
  2. Python深度学习(11):GAN生成青蛙图片
  3. 俄罗斯套娃信封问题【python实现】
  4. As3 一些设计手法笔记
  5. 在线压缩视频的方法,一键压缩视频文件
  6. 基于动态阈值检测丝网破损
  7. ssh框架下的关联表删除(级联删除)
  8. python线程创建对象_Python使用面向对象方式创建线程实现12306售票系统
  9. 机器学习模型常用评价指标(Accuracy, Precision, Recall、F1-score、MSE、RMSE、MAE、R方)
  10. 避免双击文件夹每次都打开一个新窗口