课程表【LC207】
你这个学期必须选修
numCourses
门课程,记为0
到numCourses - 1
。在选修某些课程之前需要一些先修课程。 先修课程按数组
prerequisites
给出,其中prerequisites[i] = [ai, bi]
,表示如果要学习课程ai
则 必须 先学习课程bi
。
- 例如,先修课程对
[0, 1]
表示:想要学习课程0
,你需要先完成课程1
。请你判断是否可能完成所有课程的学习?如果可以,返回
true
;否则,返回false
。
-
思路
由于在选修课程
ai
前 必须 先选修bi
,因此我们可以构建一条由bi
指向ai
的边,然后使用拓扑排序,优先遍历入度为0的节点,并将其加入拓扑排序数组中,如果最后数组的大小与节点个数不相同,那么证明有向图中有环存在,不可能完成所有课程 -
实现
class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { Deque<Integer> queue = new LinkedList<>(); int[] inDeg = new int[numCourses]; List<Integer>[] after = new List[numCourses]; Arrays.setAll(after, e -> new ArrayList<>()); for (int[] pre : prerequisites){ inDeg[pre[0]]++; after[pre[1]].add(pre[0]); } List<Integer> sorted = new ArrayList<>(); for (int i = 0; i < numCourses; i++){ if (inDeg[i] == 0){ queue.addLast(i); } } while(!queue.isEmpty()){ int x = queue.pollFirst(); sorted.add(x); for (int y : after[x]){ inDeg[y]--; if (inDeg[y] == 0){ queue.addLast(y); } } } return sorted.size() == numCourses; } }
-
复杂度
-
时间复杂度: O ( E + V ) O(E+V) O(E+V), E E E表示邻边的跳数,V为结点的个数
-
空间复杂度: O ( V ) O(V) O(V)
-
-