你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
- 例如,先修课程对
[0, 1]表示:想要学习课程0,你需要先完成课程1。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。
解题入口:
解此题的关键把此题转化有向图,那些不依赖其他课程的入度就为0,从入度为0的入手,依次减少依赖此入度为0课程的入度,如果此依赖课程的入度也为0了,就看后面的依赖,直到所有的课程入度都为0
java
public boolean canFinish(int numCourses, int[][] prerequisites) {
// 构建入度map
Map<Integer, Integer> inDegree = new HashMap<>();
// 构建当前课程关联的后续课程Map<Inteter,List<Integer>>
Map<Integer, List<Integer>> relation = new HashMap<>();
// 初始化入度
for (int i = 0; i < numCourses; i++) {
inDegree.put(i, 0);
}
// 根据关系计算入度和关联map
for (int[] prerequisite : prerequisites) {
int next = prerequisite[0];
int pre = prerequisite[1];
// 更新入度
inDegree.put(next, inDegree.get(next) + 1);
if (!relation.containsKey(pre)) {
relation.put(pre, new ArrayList<>());
}
List<Integer> relationList = relation.get(pre);
relationList.add(next);
}
Deque<Integer> deque = new LinkedList<>();
inDegree.forEach((k, v) -> {
if (v == 0) {
deque.offer(k);
}
});
// 循环根据入度为0的,减少后续课程的入度
while (!deque.isEmpty()) {
Integer zeroDegree = deque.poll();
if (!relation.containsKey(zeroDegree)) {
continue;
}
List<Integer> list = relation.get(zeroDegree);
for (Integer updateDegree : list) {
inDegree.put(updateDegree, inDegree.get(updateDegree) - 1);
if (inDegree.get(updateDegree) == 0) {
deque.offer(updateDegree);
}
}
}
// 如果入度还有不为0的,则完不成 false
for (int key : inDegree.keySet()) {
if (inDegree.get(key) != 0) {
return false;
}
}
return true;
}