力扣207.课程表
题目
你这个学期必须选修 numCourses
门课程,记为 0
到 numCourses - 1
。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites
给出,其中 prerequisites[i] = [ai, bi]
,表示如果要学习课程 ai
则 必须 先学习课程 bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。
请你判断是否可能完成所有课程的学习?如果可以,返回 true
;否则,返回 false
解题思路
用有向图描述依赖关系
有向图有入度和出度的概念:
如果存在一条有向边A—>B,则这条边给A增加了一个出度,给B增加了一个入度
每次只能选你能上的课
(1)每次只能选入度为0的课,因为它不依赖别的课,是当下能上的课
(2)假设选了0,课3的先修课少了一门,入度由2变1
(3)接着选1,导致课3的入度变0,课4的入度变为1
(4)接着选2,导致课4的入度变0
(5)现在,课3和课4的入度为0,继续选入度为0的课,直到选不到入度为0的课
代码
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<>());
for(int[] cp : prerequisites) {
indegrees[cp[0]]++;
adjacency.get(cp[1]).add(cp[0]);
}
for(int i = 0; i < numCourses; i++)
if(indegrees[i] == 0) queue.add(i);
while(!queue.isEmpty()) {
int pre = queue.poll();
numCourses--;
for(int cur : adjacency.get(pre))
if(--indegrees[cur] == 0) queue.add(cur);
}
return numCourses == 0;
}
}