先看道题吧
There are a total of numCourses
courses you have to take, labeled from 0
to numCourses-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?
Example 1:
Input: numCourses = 2, prerequisites = [[1,0]] Output: true Explanation: There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: numCourses = 2, prerequisites = [[1,0],[0,1]] Output: false Explanation: 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.
大概意思就是给你一个课程表,你需要去上这些课,但这些课是有依赖关系的。用[0,1]这样的数组表示,要上0号课就先得上1号课。判断能否完成全部课程?我看完是一脸懵逼,看了讨论区的解释,需要用到拓扑排序(Topological sorting)。好吧用自己的话来解释一下。其实就是在有向无环图中,找到一条无重复的路径且有依赖关系的路径。
首先解释一下度的概念,度分为出度和入度。在图中,其他节点指向该节点的是入度,该节点指向其他节点的则是出度。本题中,就是一门课作为另外一门课的前驱,被依赖的则出度为1,依赖的则入读为1如下图
Example Input: numCourses = 4, prerequisites = [[0,3],[1,2],[2,3]]的图如下
这道题可以用Kahn's algorithm解决,将度为0的节点加入队列,然后将其边的节点的度减一,判断节点的入度为0不,为0就加入队列,直到所有节点的入度都为0,如果该图有环则失败。
代码实现
本题可以用LinkedList来存储每个节点的依赖关系,再用一个数组来记录每个每个节点的度,用Queue来实现遍历。具体可以看注释。
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
//用来统计每个节点的关系
LinkedList<Integer>[] neigh = new LinkedList[numCourses];
//队列用来遍历入度为0的节点
Queue<Integer> queue = new LinkedList<>();
//节点的入度
int[] indegree = new int[numCourses];
//初始化
for (int i=0; i<numCourses; i++) neigh[i] = new LinkedList<>();
//建立节点的依赖并将节点的入度加1,比如[0,1]neigh[1].add(1), indegree[0]++
for (int[] pair : prerequisites) {
neigh[pair[1]].add(pair[0]);
indegree[pair[0]]++;
}
//入度为0的节点加入队列
for (int i=0; i<numCourses; i++) {
if (indegree[i]==0) queue.offer(i);
}
//用于统计遍历的节点个数
int count = 0;
while (!queue.isEmpty()) {
int course = queue.poll();
count++;
//将该节点指向的节点的入度减1,并判断入度是否为0,然后加入队列
for (int a : neigh[course]) {
if (--indegree[a] == 0) queue.offer(a);
}
}
//入度全为0则相等,否则不等
return count == numCourses;
}
}