题目介绍
LeetCode链接:https://leetcode.com/problems/course-schedule-ii/
力扣链接:https://leetcode-cn.com/problems/course-schedule-ii/
解题思路
- 可参考上一篇我写的题目207.课程表的解题思路:
https://blog.csdn.net/XinM222/article/details/88936525 - 在下面的代码中我先用了DFS判断有无路径后,若有则通过BFS遍历出学习顺序即可!
实现代码
public int[] findOrder(int numCourses, int[][] prerequisites) {
int[] order = new int[numCourses];
int count=0;
//有向图map,第一个数字为起点,第二个list存储了该起点能到达的其他点
Map<Integer, List<Integer>> map = new HashMap<>();
//每个顶点的入度,初始化为0
int[] degree = new int[numCourses];
Arrays.fill(degree, 0);
//初始化
for(int[] a:prerequisites) {
if(map.containsKey(a[1])) {
map.get(a[1]).add(a[0]);
}
else {
List<Integer> list = new ArrayList<Integer>();
list.add(a[0]);
map.put(a[1], list);
}
degree[a[0]]++;
}
//dfs_find_course返回true则说明这个课程先决条件可实现课程的拓扑排序安排
if(!dfs_find_course(numCourses, map)) {
return new int[0];
}
Queue<Integer> queue = new LinkedList<>();
//将入度为0的点提前加入队列
for(int i=0;i < numCourses;i++) {
if(degree[i]==0) {
queue.offer(i);
}
}
//BFS过程采用了队列这种数据结构
while(!queue.isEmpty()) {
//取出v,即度为0的点
int v = queue.poll();
order[count++]=v;
//对v所连接的点进行度-1的操作
List<Integer> list = map.get(v);
if(list == null)
continue;
for(int j = 0;j < list.size();j++){
int o_v = list.get(j);
degree[o_v]--;
//判断度减一后的该点是否符合要求
if(degree[o_v]==0)
queue.offer(o_v);
}
}
return order;
}
public static boolean dfs_find_course(int numCourses,Map<Integer, List<Integer>> map) {
//path记录
boolean[] path = new boolean[numCourses];
//onepath记录从某个结点出发所经过的结点
boolean[] onepath = new boolean[numCourses];
Arrays.fill(onepath, false);
Arrays.fill(path, false);
for (int i = 0; i < numCourses; i++) {
//避免重复
if(path[i]) continue;
//若找到有环则返回false
if(dfs_find_circle(map, i, path, onepath))
return false;
}
return true;
}
public static boolean dfs_find_circle(Map<Integer, List<Integer>> map,int v,
boolean[] path,boolean[] onepath) {
/*只要是这趟路径下来的所经过的点(即一个for循环),都会被onepath标记,
假如有顶点下个点是之前走过的,证明有环*/
if (onepath[v]) return true;
//对这两数组标记
onepath[v] = path[v] = true;
//对点v相连接的点进行dfs
List<Integer> list = map.get(v);
if(list!=null) {
for(int i=0;i < list.size();i++) {
int o_v = list.get(i);
if(dfs_find_circle(map, o_v, path, onepath))
return true;
}
}
//可证明这条路径不存在闭环,则去除这个路径上的这个点
onepath[v] = false;
return false;
}
总结归纳
肯定会有更好的方法,只不过自己太懒了,copy一下自己上道题目的代码,修修改改就应付了,代码也比较冗长,大家可别学我[捂脸]~