leetcode.图.207课程表-Java

1. 具体题目

现在你总共有 n 门课需要选,记为 0 到 n-1。在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1]。给定课程总量以及它们的先决条件,判断是否可能完成所有课程的学习?

示例 1:  输入: 2, [[1,0]]   输出: true  解释: 总共有 2 门课程。学习课程 1 之前,你需要完成课程 0。所以这是可能的。

说明: 输入的先决条件是由边缘列表表示的图形,而不是邻接矩阵,可以假定输入的先决条件中没有重复的边。

2. 思路分析

本题可套用有向图的拓扑排序算法——在构造一个有向图的拓扑序列时,若所有顶点都被输出过,那么说明该图不存在环,否则该图中有环。

有效的课程表中不应存在环路,所以要求构造过程中,所有顶点都被输出过。

边缘列表存储图的形式见 https://visualgo.net/en/graphds,例如顶点 V0 指向顶点 V1 表示为 prerequisites[i][1] -> prerequisites[i][0]

3. 代码

 1 public boolean canFinish(int numCourses, int[][] prerequisites) {
 2         int[] in = new int[numCourses];
 3         for(int[] nums : prerequisites){
 4             in[nums[0]]++;      //统计各顶点入度
 5         }
 6         Stack<Integer> stack = new Stack<>();   //记录入度为 0 的顶点
 7         for(int i = 0; i < numCourses; i++){
 8             if(in[i] == 0){
 9                 stack.push(i);
10             }
11         }
12         while(!stack.empty()){
13             int course = stack.pop();
14             numCourses--;
15             for(int[] nums : prerequisites){
16                 if(nums[1] == course){  //将当前顶点连接的所有顶点的入度 -1
17                     if(--in[nums[0]] == 0) stack.push(nums[0]);  //若-1后入度为0则进栈
18                 }
19             }
20         }
21         return numCourses == 0;
22     }

猜你喜欢

转载自www.cnblogs.com/XRH2019/p/11976891.html