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 <= 20000 <= prerequisites.length <= 5000prerequisites[i].length == 20 <= ai, bi < numCoursesprerequisites[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访问了,不需要再进行搜索,返回trueflag[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!
