题目描述
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?
For example:
2, [[1,0]]
There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
2, [[1,0],[0,1]]
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.
Hints:
- This problem is equivalent to finding if a cycle exists in a directed graph. If a cycle exists, no topological ordering exists and therefore it will be impossible to take all courses.
- Topological Sort via DFS – A great video tutorial (21 minutes) on Coursera explaining the basic concepts of Topological Sort.
- Topological sort could also be done via BFS.
分析
题目等价为:检测图中是否有环
参考网址:LeetCode – Course Schedule (Java)
代码
BFS:
// BFS
public static boolean canFinish(int numCourses, int[][] prerequisites) {
// 参数检查
if (prerequisites == null) {
return false;
}
int len = prerequisites.length;
if (numCourses <= 0 || len == 0) {
return true;
}
// 记录每个course的prerequisites的数量
int[] pCounter = new int[numCourses];
for (int i = 0; i < len; i++) {
pCounter[prerequisites[i][0]]++;
}
// 用队列记录可以直接访问的course
LinkedList<Integer> queue = new LinkedList<Integer>();
for (int i = 0; i < numCourses; i++) {
if (pCounter[i] == 0) {
queue.add(i);
}
}
// 取出队列的course,判断
int numNoPre = queue.size();
while (!queue.isEmpty()) {
int top = queue.remove();
for (int i = 0; i < len; i++) {
// 该course是某个course的prerequisites
if (prerequisites[i][1] == top) {
pCounter[prerequisites[i][0]]--;
if (pCounter[prerequisites[i][0]] == 0) {
numNoPre++;
queue.add(prerequisites[i][0]);
}
}
}
}
return numNoPre == numCourses;
}
DFS:
// DFS
public static boolean canFinish2(int numCourses, int[][] prerequisites) {
// 参数检查
if (prerequisites == null) {
return false;
}
int len = prerequisites.length;
if (numCourses <= 0 || len == 0) {
return true;
}
int[] visit = new int[numCourses];
// key:course;value:以该course为prerequisites的course
HashMap<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>();
// 初始化map
for (int[] p : prerequisites) {
if (map.containsKey(p[1])) {
map.get(p[1]).add(p[0]);
} else {
ArrayList<Integer> l = new ArrayList<Integer>();
l.add(p[0]);
map.put(p[1], l);
}
}
// dfs
for (int i = 0; i < numCourses; i++) {
if (!canFinishDFS(map, visit, i)) {
return false;
}
}
return true;
}
private static boolean canFinishDFS(
HashMap<Integer, ArrayList<Integer>> map, int[] visit, int i) {
if (visit[i] == -1) {
return false;
}
if (visit[i] == 1) {
return true;
}
visit[i] = -1;
// course i是某些course的prerequisites
if (map.containsKey(i)) {
for (int j : map.get(i)) {
if (!canFinishDFS(map, visit, j)) {
return false;
}
}
}
visit[i] = 1;
return true;
}