题目:
你这个学期必须选修 numCourses
门课程,记为 0
到 numCourses - 1
。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
给出,其中 prerequisites[i] = [ai, bi]
,表示如果要学习课程 ai
则 必须 先学习课程 bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。
请你判断是否可能完成所有课程的学习?如果可以,返回 true
;否则,返回 false
。
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
int[] indegrees = new int[numCourses]; // 入度表
List<List<Integer>> adjacency = new ArrayList<>();
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++)
adjacency.add(new ArrayList<>()); // 初始化 0到n-1门课,每门课对应一个List,用于该课是谁的先修课
for (int[] cp : prerequisites) {
indegrees[cp[0]]++;
adjacency.get(cp[1]).add(cp[0]); // 该课是谁的先修课
}
// 将所有入度为 0 的节点入队
for (int i = 0; i < numCourses; i++) {
if (indegrees[i] == 0)
queue.add(i);
}
// bfs
while (!queue.isEmpty()) {
int pre = queue.poll();
numCourses--;
for (int cur : adjacency.get(pre))
if (--indegrees[cur] == 0) queue.add(cur);
}
return numCourses == 0;
}
}
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> adjacency = new ArrayList<>();
for (int i = 0; i < numCourses; i++)
adjacency.add(new ArrayList<>()); // 初始化 0到n-1门课,每门课对应一个List,用于该课是谁的先修课
int[] flags = new int[numCourses]; // 标志数组
for (int[] cp : prerequisites) {
adjacency.get(cp[1]).add(cp[0]); // 该课是谁的先修课
}
for (int i = 0; i < numCourses; i++) {
if (!dfs(adjacency, flags, i))
return false;
}
return true;
}
// 存在环返回false, 不存在返回true
private boolean dfs(List<List<Integer>> adjacency, int[] flags, int i) {
if(flags[i] == 1)
return false;
if(flags[i] == -1)
return true;
flags[i] = 1;
for(Integer j : adjacency.get(i)) {
if(!dfs(adjacency, flags, j))
return false;
}
flags[i] = -1;
return true;
}
}