题目链接:课程表Ⅱ
现在你总共有 n 门课需要选,记为 0 到 n-1。
在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]
给定课程总量以及它们的先决条件,返回你为了学完所有课程所安排的学习顺序。
可能会有多个正确的顺序,你只要返回一种就可以了。如果不可能完成所有课程,返回一个空数组。
class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
List<Integer> list = new ArrayList<Integer>();
int count = 0;
// 注意pre数组的每一维的前后关系别弄反,后者是前者的前置依赖必修课。
int[] beforeClassCounts = new int[numCourses];
List<List<Integer>> dependencyLists = new ArrayList<>();
for (int i = 0; i < numCourses; i++) {
dependencyLists.add(new ArrayList<>());
}
Queue<Integer> queue = new LinkedList<Integer>();
// 将每个课程的入度记录下来
// 将每个节点的 以该节点为前置依赖必修课的课程记录下来
for (int[] pre : prerequisites) {
beforeClassCounts[pre[0]]++;
dependencyLists.get(pre[1]).add(pre[0]);
}
// 将入度为0的课程直接入队,获取以该课程为前置必修课的课程列表,遍历这些列表,将其入度-1。
for (int i = 0;i < numCourses; i++) {
if (beforeClassCounts[i] == 0) {
queue.add(i);
}
}
// 并进行判断,若这些列表中的课程此时的入度为1,即这些课程此时可以修了,将其入队。
while (!queue.isEmpty()){
int FinishedCourse = queue.poll();
list.add(FinishedCourse);
// numCourses--; 放前后都可以
for (int cur : dependencyLists.get(FinishedCourse)) {
if ( --beforeClassCounts[cur] == 0) {
queue.add(cur);
}
}
numCourses--;
}
// 因为入队的课程已经修了,总修课程数目-1。
//当没有入度为1的课程时判断此时的已修课程数目与必修总课程numCourse的大小关系,为0则true,否则为false。
int[] result = new int[list.size()];
if (numCourses != 0) {
return new int[0];
}
for (int num : list) {
result[count++] = num;
}
return result;
}
}