There are a total of n courses you have to take, labeled from 0
to n-1
.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
Example 1:
Input: 2, [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: 2, [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should
also have finished course 1. So it is impossible.
Note:
- The input prerequisites is a graph represented by a list of edges, not adjacency matrices. Read more about how a graph is represented.
- You may assume that there are no duplicate edges in the input prerequisites.
解法:
根据题意,进修一门课之前需要先进修另一门课。这些关系通过一个二维数组作为入参传入函数。其实就是在判断一个有向图是否存在环。为了判断出是否存在环,需要记录本次遍历路径上所有经过的节点。如果遇到已经经过的,那么说明存在环。反之,则不存在环。为了提高效率,我们还可以将从每个节点开始遍历的结果存入一个数组或者map。这样在路径遍历过程中如果发现某个节点之前已经被遍历过,那么直接复用结果就行了。不用再往下重复遍历了。
// Copy from: https://leetcode.com/problems/course-schedule/discuss/480820/Simple-Java-DFS
public static boolean canFinish(int numCourses, int[][] prerequisites) {
List<Integer>[] graph = new ArrayList[numCourses];
for (int i = 0; i < numCourses; i++) {
graph[i] = new ArrayList<>();
}
for (int i = 0; i < prerequisites.length; i++) {
graph[prerequisites[i][1]].add(prerequisites[i][0]);
}
boolean[] restoredStack = new boolean[numCourses]; // 暂存路径节点
boolean[] visited = new boolean[numCourses]; //记录以节点i为起始节点的遍历结果
for (int i = 0; i < numCourses; i++) {
if (visited[i])
continue;
if (isCycle(visited, restoredStack, i, graph))
return false;
}
return true;
}
private static boolean isCycle(boolean[] visited, boolean[] restoredStack, int idx, List<Integer>[] graph) {
if (restoredStack[idx])
return true;
if (visited[idx])
return false;
visited[idx] = true;
restoredStack[idx] = true;
for (int i = 0; i < graph[idx].size(); i++) {
if (isCycle(visited, restoredStack, graph[idx].get(i), graph))
return true;
}
restoredStack[idx] = false;
return false;
}