题目: 课程表,有n个课程,[0, n-1];在修一个课程前,有可能要修前导课程;

举例:

2, [[1,0]]  修课程1前需要先修课程0

There are a total of 2 courses to take. To take course 1 you should have finished course 0. So it is possible.

2, [[1,0],[0,1]]  

There are a total of 2 courses to take. To take course 1 you should have finished course 0, and to take course 0 you should also have finished course 1. So it is impossible.

解题思路:

其本质是逆拓扑排序,因此首先要将给定的课程关系转换为邻接表存储,即将给定的图转化为邻接表;

举例说明:

4, [[1,0],[2,0],[3,1],[3,2]]

1) 代码5的for循环是为了初始化一个邻接链表的结构,[[],[],[],[],]2) 代码10的for循环是为了找到有那几个节点要依靠当前节点;其中prerequisites[0][1] = 0,prerequisites[0][0] = 1,表示课程1要依靠课程0;prerequisites[1][1] = 0,prerequisites[1][0] = 2,表示课程2依靠课程0;以此类推,则最终posts中的结果为:   [[1,2],[3],[3],[]]表示课程1,2依靠课程0,课程3依靠课程1,课程3依靠课程2,没有课程依靠课程3;3) 代码15声明了一个数组preNums,下面代码16的for循环来告诉我们这个数组是干什么的;4) 代码16的for循环中,拿出post中的每一个set,假设此时拿出的是post.get(0),则拿出的是依靠0课程才能修完课程的集合[1,2];该循环结束后,preNums=[0,1,1,2]表示0课程不依赖其他课程(0课程的出度为0),1课程依赖一个课程,2课程依赖一个课程,3课程依赖两个课程;因此preNums数组表示下标的课程依赖几个其他的课程5) 到此为止,我们记录了下标课程被哪几个课程依赖,即posts;下标课程自己依赖几个课程,即preNums数组;到这里可以看出我们使用的逆拓扑结构的思想;即找出preNums数组中为0的那个下标课程(在图中表示出度为0),代码27行的for循环就是干这个事情的;6) 假设此时没有找到出度为0的那个课程,则表示课程中有相互依赖的情况,则直接return false; 如果找到出度为0的那个课程,在此例子中为课程0,而此时课程0在post中可以得出其被[1,2]课程依赖,因此需要删除0节点,那么相应的也要删掉课程1和课程2分别对课程0的依赖,那此时,需要更新preNums数组,即1课程所依赖的课程数减一,    2课程所依赖的课程数减一,则此时preNums = [-1, 0, 0, 2],-1表示已经删除了0节点。循环5,6)则可以判断中课程是否可以顺利修完,即给出的数组是否是一个逆拓扑结构;
 1 public class Solution {
 2     public boolean canFinish(int numCourses, int[][] prerequisites) {
 3         // init the adjacency list
 4         List<Set> posts = new ArrayList<Set>();
 5         for (int i = 0; i < numCourses; i++) {
 6             posts.add(new HashSet<Integer>());
 7         }
 8
 9         // fill the adjacency list,找到有哪几个点要依靠该点
10         for (int i = 0; i < prerequisites.length; i++) {
11             posts.get(prerequisites[i][1]).add(prerequisites[i][0]);
12         }
13
14         // count the pre-courses
15         int[] preNums = new int[numCourses];  // 计算下标的课程依赖几个课程
16         for (int i = 0; i < numCourses; i++) {
17             Set set = posts.get(i);
18             Iterator<Integer> it = set.iterator();
19             while (it.hasNext()) {
20                 preNums[it.next()]++;
21             }
22         }
23         // remove a non-pre course each time
24         for (int i = 0; i < numCourses; i++) {
25             // find a non-pre course
26             int j = 0;
27             for ( ; j < numCourses; j++) {   // 找到出度为0的点,删掉,并更新依靠该点的前驱点的个数
28                 if (preNums[j] == 0) break;
29             }
30
31             // if not find a non-pre course
32             if (j == numCourses) return false;
33
34             preNums[j] = -1;
35
36             // decrease courses that post the course
37             Set set = posts.get(j);
38             Iterator<Integer> it = set.iterator();
39             while (it.hasNext()) {
40                 preNums[it.next()]--;    // 删除依赖j节点的节点的出度
41             }
42         }
43
44         return true;
45     }
46 }


转载于:https://www.cnblogs.com/leavescy/p/5887013.html

Leetcode207---课程表(逆拓扑排序)相关推荐

  1. DFS实现逆拓扑排序

    多思考递归的过程! //DFS实现逆拓扑排序 bool visited[MaxVertexNum]; void DFSTraverse(Graph G){for(v=0;v<G.vexnum;v ...

  2. [力扣c语言实现]207. 课程表(拓扑排序)

    207. 课程表(拓扑排序) 1. 题目描述 2.代码如下 1. 题目描述 你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 . 在选修某些课程之前需要一些 ...

  3. 拓扑排序及逆拓扑排序

    拓扑排序其实就是对有向无环图的顶点的一种排序,每个顶点出现且只出现一次. 对一个AOV网进行拓扑排序的方法: 1.从AOV网中选择一个入度为0的顶点并输出: 2.从网中删除该顶点和所有以它为起点的有向 ...

  4. 图的逆拓扑排序(回路识别)

    目录 背景 实现思路 代码 背景 在学习拓扑排序的时候,老师提出了一个问题:在逆拓扑排序算法中如何识别出回路? 总所周知,拓扑排序必须在DAG(有向无环图)中实现,也就是说如果给定的图带有回路,就无法 ...

  5. 图——深度优先遍历(DFS)实现有向无环图的逆拓扑排序

    对图的深度遍历与对树的深度遍历思想类似,采用的是递归函数的办法. 如果是非连通图,则DFS遍历所有顶点即可. //Graph 图 //vertex 顶点,用一个int型变量表示//返回有向图G中顶点v ...

  6. 207.课程表 | 210.课程表II(拓扑排序)

    207.课程表 你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 . 在选修某些课程之前需要一些先修课程. 先修课程按数组 prerequisites 给出 ...

  7. [Leedcode][JAVA][第210 题][课程表 II][拓扑排序][BFS][DFS][有向图]

    [问题描述][第210 题][课程表 II][中等] 现在你总共有 n 门课需要选,记为 0 到 n-1.在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用 ...

  8. LeetCode 207. 课程表(拓扑排序)

    1. 题目 你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 . 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个 ...

  9. 天池 在线编程 课程表(拓扑排序 + 回溯)

    文章目录 1. 题目 2. 解题 1. 题目 总共有n个课程,从0到n-1. 有些课程可能有先决条件,例如,你想修课程0,你必须先修一门课程1,这两门课之间的关系表示为:[0,1] 给定课程的总数和先 ...

  10. 拓扑排序与逆拓扑排序

最新文章

  1. SQL 2008 安装资料及下载地址
  2. 中国高性能计算机TOP100出炉 曙光联想并列第一
  3. 百会CRM教你在大数据平台中做精准营销
  4. [学习笔记] 乱世之神杀疯了 —— K-D tree
  5. vocabulary of ERP
  6. 公众号精选评论点赞_12月评论:前10名和编辑精选
  7. W - C/C++练习7---求某个范围内的所有素数
  8. HDU.1007 Quoit Design
  9. try……catch的异常捕获机制
  10. Adobe Flash 离线安装包下载
  11. 10个大数据思维原理,你了解多少?
  12. 在SPSS中将统计表格外观修改为三线表外观的步骤
  13. 行政区域村级划分数据库_两区划定数据库规范
  14. 龟兔赛跑Description乌龟与兔子在马路上赛跑,马路边可以随地进行休息。
  15. php exec 命令,概述PHP命令行shell_exec()使用
  16. 四川夏季避暑好去处,十大清凉景点大推荐哦~
  17. 帆软通过js删除数据库表中的数据
  18. Linux服务器批量管理工具 - TeamRemote
  19. android开发中中按钮 变成红边白底,PS人像换红底为白底等的处理
  20. 统计学习方法李航版第十章部分课后习题python答案

热门文章

  1. java redis源码分析,慢谈 Redis 实现分布式锁 以及 Redisson 源码解析
  2. java jvm参数获取_在java代码中获取JVM参数
  3. django manage.py model 删除表后怎么重新生成数据库表
  4. kubernetes kubeadm init this version of kubeadm only supports deploying clusters kubeadm版本降级
  5. HyperLeger Composer 重启 | 进入play ground | 进入 couchdb
  6. 基于SSM的NBA篮球球队运营系统
  7. PHP 单元测试问题记录
  8. PHP压缩html网页代码(清除空格,换行符,制表符,注释标记)
  9. Spring MVC @ExceptionHandler、@ControllerAdvice、@RestControllerAdvice 统一异常处理
  10. linux单用户可以删除文件么,Linux单用户模式详解 及应用场景