题目: 课程表,有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)则可以判断中课程是否可以顺利修完,即给出的数组是否是一个逆拓扑结构;
 public class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
// init the adjacency list
List<Set> posts = new ArrayList<Set>();
for (int i = 0; i < numCourses; i++) {
posts.add(new HashSet<Integer>());
} // fill the adjacency list,找到有哪几个点要依靠该点
for (int i = 0; i < prerequisites.length; i++) {
posts.get(prerequisites[i][1]).add(prerequisites[i][0]);
} // count the pre-courses
int[] preNums = new int[numCourses]; // 计算下标的课程依赖几个课程
for (int i = 0; i < numCourses; i++) {
Set set = posts.get(i);
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
preNums[it.next()]++;
}
}
// remove a non-pre course each time
for (int i = 0; i < numCourses; i++) {
// find a non-pre course
int j = 0;
for ( ; j < numCourses; j++) { // 找到出度为0的点,删掉,并更新依靠该点的前驱点的个数
if (preNums[j] == 0) break;
} // if not find a non-pre course
if (j == numCourses) return false; preNums[j] = -1; // decrease courses that post the course
Set set = posts.get(j);
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
preNums[it.next()]--; // 删除依赖j节点的节点的出度
}
} return true;
}
}
												

Leetcode207--->课程表(逆拓扑排序)的更多相关文章

  1. HDOJ 2647 Reward 【逆拓扑排序+分层】

    题意:每一个人的基础工资是888. 因为一部分人要显示自己水平比較高,要求发的工资要比其它人中的一个人多.问你能不能满足他们的要求,假设能的话终于一共要发多少钱,假设不能就输出-1. 策略:拓扑排序. ...

  2. 逆拓扑排序 HDU2647Reward

    这个题如果用邻接矩阵的话,由于n比较大,会超内存,所以选用邻接表的形式.还有就是这个题有那个等级的问题,一级比一级的福利高,所以不能直接拓扑排序,而是反过来,计算出度,找出度为0的顶点,然后更新出度数 ...

  3. [LeetCode] 207. 课程表(拓扑排序,BFS)

    题目 现在你总共有 n 门课需要选,记为 0 到 n-1. 在选修某些课程之前需要一些先修课程. 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们: [0,1] 给定课程总量 ...

  4. 逆拓扑排序 Reward HDU - 2647

    Reward HDU - 2647 题意:每个人的起始金额是888,有些人觉得自己做的比另一个人好所以应该多得一些钱,问最少需要花多少钱,如果不能满足所有员工的要求,输出 -1 样例1: 2 1 1 ...

  5. 拓扑排序 --- hdu 4948 : Kingdom

    Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  6. hdu2647 逆拓扑,链式前向星。

    pid=2647">原文地址 题目分析 题意 老板发工资,可是要保证发的工资数满足每一个人的期望,比方A期望工资大于B,仅仅需比B多1元钱就可以.老板发的最低工资为888元.输出老板最 ...

  7. POJ3687.Labeling Balls 拓扑排序

    Labeling Balls Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13201 Accepted: 3811 Descr ...

  8. PKU 3687 Labeling Balls(拓扑排序)

    题目大意:原题链接 给出N个未编号的质量各不相同的球,以及它们质量轻重的大小关系,给它们从1-N贴标签编号,无重复.问是否存在可行的编号方法,不存在输出-1, 如果存在则输出唯一一种方案,此方案是使得 ...

  9. POJ3687 Labeling Balls(拓扑排序\贪心+Floyd)

    题目是要给n个重量1到n的球编号,有一些约束条件:编号A的球重量要小于编号B的重量,最后就是要输出字典序最小的从1到n各个编号的球的重量. 正向拓扑排序,取最小编号给最小编号是不行的,不举出个例子真的 ...

随机推荐

  1. Redhat/CentOS 软件安装

    概述 软件包简介 rpm 包安装 yum 在线安装 源码包管理 软件包分类 源码包 二进制包(rpm包.系统默认包) rpm包安装 rpm包的依赖性 树形依赖: a -> b -> c 环 ...

  2. 洛谷P3959 宝藏(模拟退火乱搞)

    题意 题目链接 题面好长啊...自己看吧.. Sol 自己想了一个退火的思路,没想到第一次交85,多退了几次就A了哈哈哈 首先把没用的边去掉,然后剩下的边从小到大排序 这样我们就得到了一个选边的序列, ...

  3. 关于ev||event事件对象的兼容写法

    因为FireFox Chrome默认都是有一个值传进来的,所以这里是对IE和FireFox Chrome做了兼容. 例如:页面点击事件事件要使用document,获取鼠标位置 document.onc ...

  4. Android Studio maven-metadata.xml 卡着不动原因和解决方法

    头一天好好的,第二天就卡着了. 一直在这个地方不动,如果停止就会报 Error:Could not run build action using Gradle distribution ‘https: ...

  5. ABAP system landscape和vue项目webpack构建的最佳实践

    基于Netweaver的ABAP transport route一般都有dev,test和prod三种类型的系统. 而Vue前端项目的webpack build设置也类似. 以SAP成都研究院数字创新 ...

  6. ping请求超(iPV4)

    ping请求超(iPV4) arp –a(查看局域网全部IP) cmd 管理员运行 netsh winsock reset(重置Winsock目录借以恢复网络) etsh int ip reset r ...

  7. Hbase 完全分布式 高可用 集群搭建

    1.准备 Hadoop 版本:2.7.7 ZooKeeper 版本:3.4.14 Hbase 版本:2.0.5 四台主机: s0, s1, s2, s3 搭建目标如下: HMaster:s0,s1(备 ...

  8. 吐槽在cocos2dx游戏接入腾讯信鸽的坑

    腾讯信鸽是用来在后台推送消息给移动应用客户端使用,接入方法很简单,在信鸽官网注册个账号 http://xg.qq.com/xg,然后注册一个应用,在后台页面获得ACCESS ID, ACCESS KE ...

  9. 【转】Matlab的regionprops详解

    matlab函数_连通区域 1. matlab函数bwareaopen──删除小面积对象格式:BW2 = bwareaopen(BW,P,conn)作用:删除二值图像BW中面积小于P的对象,默认情况下 ...

  10. [转]LLE

    原始特征的数量可能很大,或者说样本是处于一个高维空间中,通过映射或变换的方法,降高维数据降低到低维空间中的数据,这个过程叫特征提取,也称降维. 特征提取得基本任务研究从众多特征中求出那些对分类最有效的 ...