Medium
思想
- 图(graph), 有向图,单向
- 拓扑排序, 每个顶点一个入度,一个出度。此题关心点为“入度”
- 每次输出一个点后,就需要将这个点从图中抹掉,其后置点的入度就会-1
- 每次输出入度为0的点,意为已修完所有前置课程
- 遍历给定二维数组,统计所有顶点的入度
- 从入度为0的点开始,做BFS遍历
过程
- 定义数组:存每个顶点的入度
- 定义map:key->顶点数据; value->该顶点的右侧邻接顶点(list)
- 如何得到map(图)?
- for循环遍历二维数组,完成数组和map
- 每个pair的左边是要上的课,就在数组里+1,入度+1
- pair右边是前置课,就是map的key值。
- 如果map里有,就把当前key的value list中加一个这个pair左边的课,就是完成右边前置课才能上的课(这里map和给定数组的左右是相反的,有点混乱)
- 如果没有,就new一个arraylist,把左边的课放进去,之后和右边的课一起放进map里
- 如何通过图得到拓扑排序?BFS
- 先把所有初始入度为0的排进queue
- 开始BFS
- queue里都是入度为0的课程,poll出一个,新建list等于这个poll出值在map里的value list
- for循环将list里的值的入度逐个减1,注意判定条件要兼顾这个list是否为null
- 每次减完1后立刻判定入度是否为0,如果为0,则加入queue
- BFS结束后判定入度数组是否都为0,是则true,不是返回false
代码
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
int h = prerequisites.length;
int[] inDegree = new int[numCourses];
Map<Integer, List<Integer>> map = new HashMap<>();
for(int i = 0; i < h; i++){
inDegree[prerequisites[i][0]]++;
if(map.containsKey(prerequisites[i][1])){
map.get(prerequisites[i][1]).add(prerequisites[i][0]);
}else{
List<Integer> list = new ArrayList<>();
list.add(prerequisites[i][0]);
map.put(prerequisites[i][1], list);
}
}
Queue<Integer> q = new LinkedList<>();
for(int i = 0; i < numCourses; i++){
if(inDegree[i] == 0)
q.offer(i);
}
while(!q.isEmpty()){
int cur = q.poll();
List<Integer> curList = map.get(cur);
for(int i = 0; curList != null && i < curList.size(); i++){
inDegree[curList.get(i)]--;
if(inDegree[curList.get(i)] == 0)
q.offer(curList.get(i));
}
}
for(int i = 0; i < numCourses; i++){
if(inDegree[i] != 0)
return false;
}
return true;
}
}