我真的记不住啊 啊啊啊啊
class Solution {
//graph inDegree queue completed
public boolean canFinish(int numCourses, int[][] prerequisites) {
// 第一步:创建课程依赖关系图
// graph是一个数组,每个元素是一个List,表示该课程被哪些课程依赖
// 例如:graph[0] = [1,2] 表示课程0是课程1和课程2的先修课
List<Integer>[] graph = new ArrayList[numCourses];
// 初始化每个课程的依赖列表
for (int i = 0; i < numCourses; i++) {
graph[i] = new ArrayList<>();
}
// 第二步:创建入度数组
// inDegree[i]表示课程i有多少个先修课
// 例如:inDegree[1]=2 表示课程1有2门先修课
int[] inDegree = new int[numCourses];
// 第三步:填充依赖图和入度数组
for (int[] edge : prerequisites) {
int course = edge[0]; // 当前课程
int prereq = edge[1]; // 先修课程
// 在先修课程的依赖列表中添加当前课程
graph[prereq].add(course);
// 当前课程的先修课数量+1
inDegree[course]++;
}
// 第四步:初始化队列
// 把所有没有先修课的课程加入队列
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (inDegree[i] == 0) {
queue.offer(i); // 入队
}
}
// 第五步:开始处理课程
int completed = 0; // 已完成的课程计数
while (!queue.isEmpty()) {
// 取出一个可以学习的课程
int current = queue.poll();
completed++;
// 查看这个课程被哪些课程依赖
for (int dependent : graph[current]) {
// 这些依赖课程的先修课数量-1
inDegree[dependent]--;
// 如果某个依赖课程不再有先修课了
if (inDegree[dependent] == 0) {
// 就可以开始学习这个课程了
queue.offer(dependent);
}
}
}
// 第六步:检查是否所有课程都能完成
// 如果完成的课程数等于总课程数,说明可以完成
// 否则说明存在循环依赖,无法完成所有课程
return completed == numCourses;
}
}