1+ // 207. 课程表
2+
3+
4+ /*
5+ 拓扑排序,广度优先搜索
6+ 1、入度数组 inDegree 记录每门课程的入度
7+ 2、邻接表 adjacent,key为课程号,value为依赖该课程的其他课程号数组
8+ 3、遍历先修课程数组 prerequisites,更新入度数组 inDegree 和邻接表 adjacent
9+ 4、队列 queue 存放入度为0的课程号,即没有先修课程,可以选修
10+ 5、从队列弹出课程号,表示该课程已修。然后获取已修课程的后继课程列表 successorList,更新所有后继课程的入度减1。
11+ 当后继课程入度为0时,则该课程可选修,将课程号存入队列。循环从队列弹出处理,直到没有可选修的课程
12+ 6、遍历入度数组 inDegree,判断所有课程号入度是否为0,不为0则不能修完所有课程,为0则能修完
13+
14+ 示例:n = 6,先决条件表:[[3, 0], [3, 1], [4, 1], [4, 2], [5, 3], [5, 4]]
15+ 课程 0, 1, 2 没有先修课,可以直接选。其余的课,都有两门先修课。
16+ 用有向图来展现这种依赖关系(做事情的先后关系),这种叫 有向无环图,把一个 有向无环图 转成 线性的排序 就叫 拓扑排序。
17+ 拓扑排序是将 有向无环图 所有顶点排成一个线性序列,使得图中任意一对顶点 u 和 v,若边 <u,v> ∈ E(G),则 u 在线性序列中出现在 v 之前
18+ 有向图有 入度 和 出度 的概念:如果存在一条有向边 A --> B,则这条边给 A 增加了 1 个出度,给 B 增加了 1 个入度。
19+ 所以,顶点 0、1、2 的入度为 0,顶点 3、4、5 的入度为 2
20+ 拓扑排序过程:
21+ 1)先统计所有节点的入度
22+ 2)将入度为0的端点输出,删除该端点和该端点出发的有向边,并将后继端点入度减1
23+ 3)重复步骤2,如果最后有入度不为0的端点说明存在环,不存在拓扑排序,否则存在拓扑排序
24+
25+ 0
26+ ↘
27+ 3
28+ ↗ ↘
29+ 1 5 拓扑排序:0 1 2 3 4 5
30+ ↘ ↗
31+ 4
32+ ↗
33+ 2
34+ */
35+ class Solution {
36+ public boolean canFinish (int numCourses , int [][] prerequisites ) {
37+ Map <Integer , Integer > inDegree = new HashMap <>();
38+ for (int i = 0 ; i < numCourses ; i ++) {
39+ inDegree .put (i , 0 );
40+ }
41+ Map <Integer , List <Integer >> adjacent = new HashMap <>();
42+ for (int [] relate : prerequisites ) {
43+ int cur = relate [1 ];
44+ int next = relate [0 ];
45+ inDegree .put (next , inDegree .get (next ) + 1 );
46+ if (!adjacent .containsKey (cur )) {
47+ adjacent .put (cur , new ArrayList <>());
48+ }
49+ adjacent .get (cur ).add (next );
50+ }
51+ Queue <Integer > queue = new LinkedList <>();
52+ for (int key : inDegree .keySet ()) {
53+ if (inDegree .get (key ) == 0 ) {
54+ queue .offer (key );
55+ }
56+ }
57+ while (!queue .isEmpty ()) {
58+ int cur = queue .poll ();
59+ if (!adjacent .containsKey (cur )) {
60+ continue ;
61+ }
62+ List <Integer > successorList = adjacent .get (cur );
63+ for (int next : successorList ) {
64+ inDegree .put (next , inDegree .get (next ) - 1 );
65+ if (inDegree .get (next ) == 0 ) {
66+ queue .offer (next );
67+ }
68+ }
69+ }
70+ for (int key : inDegree .keySet ()) {
71+ if (inDegree .get (key ) != 0 ) {
72+ return false ;
73+ }
74+ }
75+ return true ;
76+ }
77+ }
0 commit comments