package leetcode.top100;
import java.util.*;
public class Timetable {
public static boolean canFinish(int numCourses, int[][] prerequisites) {
/**
* 核心思想是用类似广度优先遍历
* 1.先遍历prerequisites数组,计算入度。
*
*/
// 1.计算课程号和其对应节点的入度
HashMap<Integer, Integer> inDegree = new HashMap<>();
// 将课程放入
for (int i = 0; i < numCourses; i++) {
inDegree.put(i,0);
}
//2.依赖关系。存储依赖关系
HashMap<Integer, List<Integer>> adj = new HashMap<>();
// 初始化入度和依赖关系 a.算出每个节点的入度。 b.算出每个节点是谁的上个节点,也就是谁的先修课
for (int[] relate : prerequisites){
// (3,0), 想学3号课程要先完成0号课程, 更新3号课程的入度和0号课程的依赖(邻接表)
int cur = relate[0];
int before = relate[1];
// (1).更新入度
inDegree.put(cur,inDegree.get(cur)+1);
// 2.当前节点的邻接表
if (!adj.containsKey(before)){
adj.put(before,new ArrayList<>());
}
adj.get(before).add(cur);
}
// 3.BFS, 将入度为0的课程放入队列, 队列中的课程就是没有先修, 可以学的课程
Queue<Integer> queue = new LinkedList<>();
for (int key:inDegree.keySet()){
if (inDegree.get(key)==0){
queue.add(key);
}
}
// 取出一个节点, 对应学习这门课程.
// 遍历当前邻接表, 更新其入度; 更新之后查看入度, 如果为0, 加入到队列
while (!queue.isEmpty()){
Integer cur = queue.poll();
// 遍历当前课程的邻接表, 更新后继节点的入度
if (!adj.containsKey(cur)){
continue;
}
// 当前节点代表课程是哪些课程先修课
List<Integer> impactList = adj.get(cur);
for (int k:impactList){
inDegree.put(k,inDegree.get(k)-1);
if (inDegree.get(k)==0){
queue.add(k);
}
}
}
// 4.遍历入队, 如果还有课程的入度不为0, 返回fasle
for (int key:inDegree.keySet()){
if (inDegree.get(key)!=0){
return false;
}
}
return true;
}
public static void main(String[] args) {
int[][] course = new int[][]{
{1,0}
};
boolean res = canFinish(6, course);
System.out.println(res);
}
}
转载评论:https://leetcode.cn/problems/course-schedule/solutions/250377/bao-mu-shi-ti-jie-shou-ba-shou-da-tong-tuo-bu-pai-/