(Leetcode)判断一个图是否是可以拓扑排序的——使用Queue
2016-12-04 23:30
357 查看
207. Course Schedule
拓扑排序 Topological Order对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。
通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。
简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
There are a total of n courses you have to take, labeled from 0 to n - 1.
Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1]
Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?
For example:
2, [[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.
分析
通过计算所有点的inDegree(入度),找到拓扑序列中可能是开头的点(inDegree[node]==0)。将这些点加入队列queue。遍历队列,对每一个队列中的点cur_node:
找到他的一个post_node,并将inDegree[post_node]- -
如果inDegree[post_node]==0 ,把post_node也加入队列。
遍历所有inDegree,如果inDegree[node]!=0。说明图中有环,说明有node没有被加入queue。
(那只可能是因为这个node在他的pre_node还没被访问到的时候,就被访问了。)
Code
public class Solution { public boolean canFinish(int numCourses, int[][] prerequisites) { if (numCourses <= 0) return false; Queue<Integer> queue = new LinkedList<Integer>(); //LinkedList实现了Queue接口 int inDegree[] = new int[numCourses]; for(int i=0; i<prerequisites.length; i++){ inDegree[prerequisites[i][1]]++; } for(int i=0; i<numCourses; i++){ if(inDegree[i]==0){// this node don't have prenode queue.offer(i); } } Integer curNode; while((curNode = (Integer)queue.poll())!=null){ for(int i=0; i<prerequisites.length; i++){ if(prerequisites[i][0]==curNode){ inDegree[prerequisites[i][1]]--; if(inDegree[prerequisites[i][1]]==0){ queue.offer(prerequisites[i][1]); } } } } for(int i=0; i<numCourses; i++){ if(inDegree[i]!=0) return false; } return true; } }
java Queue中 remove/poll, add/offer, element/peek区别
offer,add区别:
一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。这时新的 offer 方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。
poll,remove区别:
remove() 和 poll() 方法都是从队列中删除第一个元素。remove() 的行为与 Collection 接口的版本相似,但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。
peek,element区别:
element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null相关文章推荐
- oracle的常用函数 instr() 和substr()函数 博客分类: oracle 在Oracle中 可以使用instr函数对某个字符串进行判断,判断其是否含有指定的字符。 在一个
- 每天一道LeetCode-----存在一个由加油站组成的环路,判断是否可以从某个加油站出发环绕一周
- 判断一个文件是否可以使用
- 不使用循环或递归判断一个数是否为3的幂(leetcode 326)
- 在进行C#编程时候,有的时候我们需要判断一个字符串是否是数字字符串,我们可以通过以下两种方法来实现。 【方法一】:使用 try{} catch{} 语句。 我们可以在try语句块中试图
- C#判断一个string是否可以为数字
- C#判断一个string是否可以为数字
- [总结]C#判断一个string是否可以为数字,五种解决方案!
- 判断一个string是否可以为数字
- 判断一个string是否可以为数字
- 判断一个string是否可以为数字
- C#判断一个string是否可以为数字,五种解决方案!
- 判断一个string是否可以为数字
- 如何判断一个文件是否正在被使用
- 判断一个string是否可以为数字
- 使用位运算判断一个数是否为2的N次方
- C#判断一个string是否可以为数字的五种解决方案
- 如何快速判断一个整数是否可以整除另一个整数的理论分析
- [总结]C#判断一个string是否可以为数字,五种解决方案!
- 判断一个数是否可以表示为k个连续的数之和