描述
现在你总共有 n 门课需要选,记为 0 到 n - 1.
一些课程在修之前需要先修另外的一些课程,比如要学习课程 0 你需要先学习课程 1 ,表示为[0,1]
给定n门课以及他们的先决条件,判断是否可能完成所有课程?
样例
给定 n = 2,先决条件为 [[1,0]] 返回 true
给定 n = 2,先决条件为 [[1,0],[0,1]] 返回 false
代码
public class Solution {
/**
* @param numCourses a total of n courses
* @param prerequisites a list of prerequisite pairs
* @return true if can finish all courses or false
*/
public boolean canFinish(int numCourses, int[][] prerequisites) {
// edges用来存储每一门课程对应的所有后续课程
// 此处新建edges的写法要注意
List[] edges = new ArrayList[numCourses];
int[] degree = new int[numCourses];
// edges[i]本身就是一个动态数组,初始化edges
for (int i = 0;i < numCourses; i++)
edges[i] = new ArrayList<Integer>();
for (int i = 0; i < prerequisites.length; i++) {
// 题目给出的prerequisites[i][1]是先修课程,prerequisites[i][0]是后续课程
// 统计学习某门课需要先修的课程数目,即入度
degree[prerequisites[i][0]]++ ;
// 即把某门课的后续课程全部加入到该课对应的edges数组中
edges[prerequisites[i][1]].add(prerequisites[i][0]);
}
// degree数组中i代表的的是某一门课程
// 把度为0的课程加入队列
Queue queue = new LinkedList();
for(int i = 0; i < degree.length; i++){
if (degree[i] == 0) {
queue.add(i);
}
}
int count = 0;
while(!queue.isEmpty()){
// 队列里存储的是Integer
int course = (int)queue.poll();
count ++;
// n代表当前课程的后续课程的数目
int n = edges[course].size();
// 每处理一门课程,该课程的后续课程的度都要-1
for(int i = 0; i < n; i++){
int pointer = (int)edges[course].get(i);
degree[pointer]--;
if (degree[pointer] == 0) {
queue.add(pointer);
}
}
}
// 处理的课程数目等于所有课程说明所有课程之间可以构成拓扑排序
return count == numCourses;
}
}