Algorithm/src/main/java/graph/CanFinish.java
2025-03-25 15:57:54 +08:00

84 lines
3.3 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package graph;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* 题目: 207. 课程表 (canFinish)
* 描述:你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
* 在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
* 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
* 请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
* 链接https://leetcode.cn/problems/course-schedule/
*/
//思路知道,代码不好写
/*
思路解析
构建图与入度数组
用一个邻接表 graph 表示课程之间的依赖关系。
对于先修课程对 [ai, bi],表示修课程 ai 之前必须完成课程 bi因此建立一条从 bi 到 ai 的边,并将 ai 的入度加 1。
初始化队列
将所有入度为 0 的课程(即没有先修要求的课程)加入队列,作为拓扑排序的起点。
拓扑排序
从队列中取出一个课程,将其计入已完成课程数量 count。
遍历该课程的所有后续课程,将这些课程的入度减 1。如果某个课程的入度减为 0则说明它所有的先修课程都已完成将其加入队列。
判断是否存在环
如果最终能处理的课程数量等于总课程数,则说明不存在环路,所有课程都可以按要求完成;否则说明存在循环依赖,无法完成所有课程。
*/
public class CanFinish {
public boolean canFinish(int numCourses, int[][] prerequisites) {
// 构建图graph.get(i) 存储课程 i 的后续课程
List<List<Integer>> graph = new ArrayList<>();
// 记录每个课程的入度(即需要先修课程的数量)
int[] indegree = new int[numCourses];
// 初始化图
for (int i = 0; i < numCourses; i++) {
graph.add(new ArrayList<>());
}
// 构建图和入度数组
// 每个先修对 [ai, bi] 表示:要修 ai 必须先修 bi
// 因此 bi 指向 ai所以 indegree[ai]++
for (int[] pre : prerequisites) {
int course = pre[0];
int preCourse = pre[1];
graph.get(preCourse).add(course);
indegree[course]++;
}
// 使用队列存储所有入度为 0 的课程
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (indegree[i] == 0) {
queue.offer(i);
}
}
// 用于统计可以修的课程数
int count = 0;
while (!queue.isEmpty()) {
int cur = queue.poll();
count++;
// 遍历当前课程的所有后续课程,将它们的入度减 1
for (int next : graph.get(cur)) {
indegree[next]--;
// 如果入度减到 0说明该课程的先修都已完成
if (indegree[next] == 0) {
queue.offer(next);
}
}
}
// 如果所有课程都能修完,则 count 应等于 numCourses
return count == numCourses;
}
}