LeetCode编程训练 - 拓扑排序(Topological Sort)

Posted bangerlee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode编程训练 - 拓扑排序(Topological Sort)相关的知识,希望对你有一定的参考价值。

拓扑排序基础

拓扑排序用于解决有向无环图(DAG,Directed Acyclic Graph)按依赖关系排线性序列问题,直白地说解决这样的问题:有一组数据,其中一些数据依赖其他,问能否按依赖关系排序(被依赖的排在前面),或给出排序结果。

 

最常用解决拓扑排序问题的方法是Kahn算法,步骤可以概括为:

1. 根据依赖关系,构建邻接矩阵或邻接表、入度数组
2. 取入度为0的数据(即不依赖其他数据的数据),根据邻接矩阵/邻接表依次减小依赖其的数据的入度
3. 判断减小后是否有新的入度为0的数据,继续进行第2步
4. 直到所有数据入度为0、得到拓扑排序序列,或返回失败(存在环形依赖)

其中2、3两个步骤取入度为0数据、减小依赖其的数据的入度,过程像树的宽度优先搜索,用到类似BFS方法;以上过程用伪代码表示如下:

L ← Empty list that will contain the sorted elements
S ← Set of all nodes with no incoming edge
while S is non-empty do
    remove a node n from S
    add n to tail of L
    for each node m with an edge e from n to m do
        remove edge e from the graph
        if m has no other incoming edges then
            insert m into S
if graph has edges then
    return error   (graph has at least one cycle)
else 
    return L   (a topologically sorted order)

 

下面看具体例子 207. Course Schedule (有n个课程,课程间有依赖关系,问能否完成所有课程):

    //207. Course Schedule
    bool canFinish(int numCourses, vector<pair<int, int>>& prerequisites) {
//构建邻接矩阵、入度数组 vector
<vector<int>> adj(numCourses); vector<int> indegree(numCourses,0); for(auto x:prerequisites){ adj[x.second].push_back(x.first); indegree[x.first]++; }
//类似BFS queue
<int> q; for(int i=0;i<numCourses;i++) if(indegree[i]==0) q.push(i); while(!q.empty()){ int cur=q.front(); q.pop(); numCourses--; for(auto next:adj[cur]) if(--indegree[next]==0) q.push(next);//新入度为0的先处理,这与正统BFS有区别 }
//判断最后所有数据入度为0
return numCourses==0; }

以上用到邻接矩阵(adjacency matrix)表示依赖关系,时间复杂度为O(V^2),其中V为数据个数。可视化过程:这里

 

相关LeetCode题:

207. Course Schedule  题解

210. Course Schedule II  题解

444. Sequence Reconstruction  题解

269. Alien Dictionary  题解

 

 
 
 

以上是关于LeetCode编程训练 - 拓扑排序(Topological Sort)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode拓扑排序

leetcode之拓扑排序刷题总结1

LeetCode 207. Course Schedule(拓扑排序)

LeetCode 207. Course Schedule(拓扑排序)

leetcode 210. 课程表 II----拓扑排序篇二

[拓扑排序] leetcode 1136 Parallel Courses