graph-TopologicalSort拓扑排序

一般我们认为,TopologicalSort是BFS中的一种。其实DFS也可以做拓扑排序,只是比较难理解。
拓扑排序适用于有向无环图(Directed Acyclic Graph)。

直观地理解:图中的节点,对于a given node,它依赖另外一个或多个点,看图中节点能否按依赖关系排序(prerequisite排在前面),并且遍历完全部节点。

题目 简介
207. Course Schedule 能否按依赖关系排序
210. Course Schedule II 求依赖关系的整个路径
269. Alien Dictionary 求依赖关系的整个路径
329. Longest Increasing Path in a Matrix 求依赖关系的最长路径
444. Sequence Reconstruction 检查是否是唯一的路径
1203. Sort Items by Groups Respecting Dependencies 还没做:)

207. Course Schedule

Input: numCourses = 2, prerequisites = [[1,0],[0,1]],问是否能把所有课都上了。Output: false

as usual, 先建构图。这个题我们已知numCourses,即节点个数已知且有限,于是可以用邻接矩阵来表示graph。

这个题除了graph,还要填写indegree,因为我们要找“改节点的所有prerequisite已经都clear了的节点”,即“indegree为零的点”,作为“当前可访问的点”,放进queue里(和BFS一样。注意“访问queue”是在出队的时候访问)。

剩下的工作就是BFS啦,由最开始的“indegree本来就是0的点”,逐渐扩散来访问,访问过当前点之后,把它的邻居indegree全都减一,因为这个点“学过了”,就清除了这个prerequisite,它的所有邻居就减少一个prerequisite。直到减到为0,就ready to visit啦,扔到队列里。

另外,这个是有向图,不需要visited数组来标记。而且访问完的点不用在graph里标记把这条边去掉,因为每个点只访问一次,边还是有序的,这个边不会再被访问了,所以无所谓。

class Solution {
   
    public boolean canFinish(int numCourses, int[][] prerequisites) {
   
        //1)把边集合转化为邻接矩阵;2)填写indegree数组
        int[][] graph = new int[numCourses][numCourses];
        int[] indegree = new int[numCourses]; //"to"
        for (int[] prerequisite : prerequisites) {
   
            int from = prerequisite[0];
            int to = prerequisite[1];
            if (graph[from][to] == 0) {
   
                indegree[to]++;
                graph[from][to] = 1;
            }
        }
        //先把indegree一开始就为零的点,放进queue里
        int count = 0;
        Queue<Integer> q = new LinkedList<>();
        for (int i = 0; i < indegree.length; i++) {
   
            if (indegree[i] == 0) {
   
                q.offer(i);
            }
        }
        //访问整个图
        while (!q.isEmpty()) {
   
            int from = q.poll();
            count++;
            //检查"from"的neighbors
            for (int i = 0; i < numCourses; i++) {
   
                if (graph[from][i] != 0) {
   
                    indegree[i]--;//更新邻居的indegree
                    if (indegree[i] == 0) {
   //prerequisite cleared
                        q.offer(i);
                    }
                }
            }
        }
        return count == numCourses;
    }
}

210. Course Schedule II

Input: 4, [[1,0],[2,0],[3,1],[3,2]],求某一个完整路径。
Output: [0,1,2,3] or [0,2,1,3]

210和209区别不大,就是增加了一个数组来记录路径即可。

class Solution {
   
    public int[] findOrder(int numCourses, int[][] prerequisites) {
   
        int[] order = new int[numCourses];//记录路径
        int index = 0;
        //1)把边集合转化为邻接矩阵;2)填写indegree数组
        boolean[][] graph =
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值