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.
思路:
宽度优先搜索,用一个数组存储每个课程的前置课程数量,用一个二维list存储每个课程可解锁的所有课程。
宽搜时,每搜索到一个课程,就把他能解锁的所有子课程的前置课程数减1,如果某个子课程前置课程数归0,就把它加入到队列中。
最后比较宽搜到的课程数是否与课程总数相等。
public boolean canFinish(int numCourses, int[][] prerequisites) {
//tip 后面的是前置条件
int[] preCount = new int[numCourses];
List<List<Integer>> unlock = new ArrayList<>();
for (int i = 0; i < numCourses; i++) {
unlock.add(new ArrayList<>());
}
for (int i = 0; i < prerequisites.length; i++) {
int[] pre = prerequisites[i];
preCount[pre[0]] += 1;
unlock.get(pre[1]).add(pre[0]);
}
//use queue to search and count
int cnt = 0;
Queue<Integer> q = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (preCount[i] == 0) {
q.offer(i);
}
}
while (!q.isEmpty()) {
int num = q.poll();
cnt++;
List<Integer> subs = unlock.get(num);
for (int i = 0; i < subs.size(); i++) {
int next = subs.get(i);
preCount[next] -= 1;
if (preCount[next] == 0) {
q.offer(next);
}
}
}
return cnt == numCourses;
}