吃完普通的食堂饭菜,回到实验室,继续做一道题!
1、题目描述
2、逻辑分析
这道题涉及到图相关知识,应用到了拓扑排序。
题意解释
- 一共有 n 门课要上,编号为 0 ~ n-1。
- 先决条件 [1, 0],意思是必须先上课 0,才能上课 1。
- 给你 n、和一个先决条件表,请你判断能否完成所有课程。
官方给的题解太抽象了,有另一个题解给的很直观,易理解,放过来:题解:课程表
3、代码演示
public boolean canFinish(int numCourses, int[][] prerequisites) {// 创建一个哈希映射,用于存储每个课程的入度(即需要先修的课程数量)Map<Integer, Integer> inDegree = new HashMap<>();// 初始化每个课程的入度为0 for(int i = 0; i < numCourses; i++){inDegree.put(i,0);}// 创建一个哈希映射,用于存储每个课程的后续课程列表Map<Integer, List<Integer>> adj = new HashMap<>();// 遍历先决条件数组 for(int[] relate : prerequisites){// 当前课程(即需要学习的课程)int cur = relate[1];// 后续课程(即当前课程的先决条件)int next = relate[0];// 更新后续课程的入度inDegree.put(next, inDegree.get(next) + 1);// 如果当前课程的后续课程列表还未初始化,则进行初始化if(!adj.containsKey(cur)){adj.put(cur, new ArrayList<>());}// 将后续课程添加到当前课程的后续课程列表中adj.get(cur).add(next);}// 创建一个队列,用于存储入度为0的课程Queue<Integer> queue = new LinkedList<>();// 将所有入度为0的课程加入队列for(int key : inDegree.keySet()){if(inDegree.get(key) == 0){queue.offer(key);}}// 拓扑排序的主循环while(!queue.isEmpty()){// 取出队首的入度为0的课程 int cur = queue.poll();// 如果当前课程没有后续课程(即没有需要它作为先决条件的课程),则跳过此次循环if(! adj.containsKey(cur)){continue;}List<Integer> successorList = adj.get(cur);// 遍历当前课程的后续课程列表 for(int k : successorList){// 更新后续课程的入度inDegree.put(k, inDegree.get(k) - 1);// 如果后续课程的入度变为0,则将其加入队列if(inDegree.get(k) == 0){queue.offer(k);}}}// 遍历所有课程的入度,如果有任何课程的入度不为0,则说明存在环,无法完成所有课程for(int key : inDegree.keySet()){if(inDegree.get(key) != 0){return false;}}// 所有课程的入度都为0,说明不存在环,可以完成所有课程 return true;}
哈哈,击败百分之十二,笑了!照着打的,看了半天还是不太懂,懂了我下次做估计也做不出来,先放这儿吧,下次再来看!