您的位置:首页 > 产品设计 > UI/UE

(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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode Queue java