LeetCode-207-课程表
题目
你这个学期必须选修 numCourses
门课程,记为 0
到 numCourses - 1
。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
给出,其中 prerequisites[i] = [ai, bi]
,表示如果要学习课程 ai
则 必须 先学习课程 bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。
请你判断是否可能完成所有课程的学习?如果可以,返回 true
;否则,返回 false
。
示例 1:
1 | 输入:numCourses = 2, prerequisites = [[1,0]] |
示例 2:
1 | 输入:numCourses = 2, prerequisites = [[1,0],[0,1]] |
提示:
1 <= numCourses <= 2000
0 <= prerequisites.length <= 5000
prerequisites[i].length == 2
0 <= ai, bi < numCourses
prerequisites[i]
中的所有课程对 互不相同
题解
这一题的思路参考:
解题思路往课程安排图是否是有向无环图(DAG)那边去靠。那么便可以用拓扑排序的方法来解决了:对DAG的顶点进行排序,对每条有向边(u, v),均有u(在排序记录中)比v先出现。或者说对于某个点v,只有v的源点都出现了,v才出现。
法一: 入度表(广度优先搜索)
算法流程:
- 统计课程安排表里每个节点的入度,并且生成入读表
indegrees
- 用队列
queue
,把所有入度为0
的节点入队; - 当
queue
非空,依次把队首节点出队,然后在课程安排图中删除该节点pre
(把该节点对于所有邻接节点cur
的入度设置为-1
,indegrees[cur] -= 1
,入度为-1
表示cur
的所有前驱节点被删除了,然后把cur
入队) - 每次
pre
出队时,执行numCourses--
;如果课程安排图是有向无环图(可安排),那么所有节点都入队并且出队过,完成了拓扑排序。如果存在环的话,一定有节点的入度始终不为0
。所以拓扑排序的出队次数等于课程个数,返回numCourses == 0
即可。
1 | class Solution { |
法二:深度优先搜索
思想为通过DFS
判断是否有环
算法流程:
- 借助一个标志列表
flags
,判断每个节点i的状态:i == 0
,未被访问、i == 1
被当前节点启动的DFS
访问、i == -1
被其他节点启动的DFS
访问 - 对
numCourses
个节点依次执行DFS
,判断每个节点起步DFS
是否有环,有直接返回false
。
DFS
流程:
-
终止条件:
flag[i] == -1
当前访问节点已经被其他节点启动的DFS
访问了,不需要再进行搜索,返回true
flag[i] == 1
,本轮DFS
节点i
被第二次访问了,有环,返回false
-
将当前访问节点i对应
flag[i]
置1
,标记访问过; -
递归访问当前节点i的所有邻接节点
j
,有环返回false
-
若当前节点的所有邻接节点都被遍历没环,
flag[i] = -1
,返回true
1 | class Solution { |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Excelius's World!