问题背景
给你一组课,课和课之间互不相同,课与课之间可以有依赖。如果要学习某一课必须先学习其依赖的课。
比如上例,课程A没有任何依赖,可以直接学习。
课程B依赖课程A,D。
相关的问题
- 207 课程表 https://leetcode.cn/problems/course-schedule/
- 210 课程表 II https://leetcode.cn/problems/course-schedule-ii/
思路
这里统一用一种方案解决:
首先将原数据给出的依赖关系转换为有向图
结构
List[]
其长度为课程数,每个节点为一个List
其中保存的是每个节点的next节点。
此外需要维护每个节点的入度
。即多少个节点指向此节点,如果这个为0,说明这个节点没有依赖。在题意的语义环境下则意味着,这门课没有依赖,可以直接学习。
后面进行广度优先搜索,将所有入度
已经为0的节点入队并加入结果集。如果找不到这样的节点,说明所有课程都相互依赖,无法开始学习。
然后开始弹出节点,每次弹出节点就从我们的图结构中取出其next节点,即依赖它的节点。将其入度
减1.如果其入度
为0,则可以入队。并且加入的结果集中。
如果最终结果集中结果数等于课程数,说明可以完成全部学习。同时结果集中的学习顺序也是可以顺序完成的,不违反依赖的学习顺序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| class Solution { public int[] findOrder(int numCourses, int[][] prerequisites) { List<Integer>[] graph = new List[numCourses]; int[] indegress = new int[numCourses];
for(int i=0;i<numCourses;i++) graph[i] = new ArrayList<>();
for(int[] prerequisite:prerequisites) { graph[prerequisite[1]].add(prerequisite[0]); indegress[prerequisite[0]]++; }
Deque<Integer> q = new ArrayDeque<>(); List<Integer> result = new ArrayList<>(); for(int i=0;i<indegress.length;i++) if(indegress[i]==0) { q.add(i); result.add(i); } while(!q.isEmpty()) { Integer poll = q.poll(); for(Integer next:graph[poll] ) { indegress[next]--; if(indegress[next]==0){ q.add(next); result.add(next); } } } if(result.size()!=numCourses) return new int[]{}; else { int[] ret= new int[numCourses]; for(int i=0;i<numCourses;i++)ret[i]=result.get(i); return ret; } } }
|