A210 有向图的拓扑排序

做LC新出的题:先行课课程表,看到了Topological Sorting.

回想起去年有次在群里跟同学讨论一道类似的题。当时还不知道Topological,就自顾自地做了一番,后来别人来一个提一次,都说用Topological。连解释都没有。我就郁闷了。后来也没看。今天总结性一次搞定。

鱼C的帖子 精简

从AOV网中选择一个没有前趋的顶点(该顶点的入度为0)并且输出它;

从网中删去该顶点,并且删去从该顶点发出的全部有向边;

重复上述两步,直到剩余网中不再存在没有前趋的顶点为止。

算法时间复杂度:

对一个具有n个顶点,e条边的网来说,初始建立入度为零的顶点栈,要检查所有顶点一次,执行时间为O(n)。

排序中,若AOV网无回路,则每个顶点入、出栈各一次,每个表结点被检查一次,因而执行时间是 O(n+e)。

所以,整个算法的时间复杂度是 O(n+e)。


CSDN拓扑排序的原理及其实现 (详细)

有向图的拓扑排序

Coursera 课程讲解


最后是LC上的代码:

public int[] findOrder(int numCourses, int[][] prerequisites){

--// nextVertex中的每个entry,int指课程,set指此课程的所有先行课

--Map> nextVertex = new HashMap<>();

--// preVertex[i] 记录课程“i”是先行课的次数

--int[] preVertex = new int[numCourses];

--// 扫描所有先行课限制

--for(int i = 0; i < prerequisites.length; i++){

----if(!nextVertex.containsKey(prerequisites[i][0])) 

------nextVertex.put(prerequisites[i][0], new HashSet<>());

----// boolean add(E e),  如果e已经存在,Set的add方法返回false。

----// 每门课只记录其第一个先行课!从第二个起add返回false,避免dup。

----if (nextVertex.get(prerequisites[i][0]).add(prerequisites[i][1]))

------preVertex[prerequisites[i][1]]++;

--}

--// BFS Queue, 

--Deque queue = new ArrayDeque<>();   

--for(int i = 0; i < preVertex.length; i++) 

----if(preVertex[i] == 0) queue.offerLast(i); // 记录所有没被当作先行课的课程

--//把不是先行课的课程依次倒着插入。

--int[] res = new int[numCourses]; // 最终输出

--int index = res.length - 1; //倒着来

--while(!queue.isEmpty()){

----int key = queue.pollFirst();

----res[index--] == key;

----// 更新此课的所有后行课

----if(nextVertex.containsKey(key)){

----for(int i:nextVertex.get(key)) // 便利set

------if(--preVertex[i] == 0) // 如果此后行课没有别的先行课了

--------queue.offerLast(i); //存入queue

----}

----numCourses; // 更新所剩课程数

--}

--// 如果课程都被包了,返回结果,不然返回新array

--return numCourses == 0 ? res

}

你可能感兴趣的:(A210 有向图的拓扑排序)