美文网首页
LeetCode-207-课程表

LeetCode-207-课程表

作者: 蒋斌文 | 来源:发表于2021-06-23 12:40 被阅读0次

    LeetCode-207-课程表

    207. 课程表

    难度中等

    你这个学期必须选修 numCourses 门课程,记为 0numCourses - 1

    在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai必须 先学习课程 bi

    • 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1

    请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false

    示例 1:

    输入:numCourses = 2, prerequisites = [[1,0]]
    输出:true
    解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。
    

    示例 2:

    输入:numCourses = 2, prerequisites = [[1,0],[0,1]]
    输出:false
    解释:总共有 2 门课程。学习课程 1 之前,你需要先完成课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。
    

    提示:

    • 1 <= numCourses <= 105
    • 0 <= prerequisites.length <= 5000
    • prerequisites[i].length == 2
    • 0 <= ai, bi < numCourses
    • prerequisites[i] 中的所有课程对 互不相同

    拓扑排序问题
    根据依赖关系,构建邻接表、入度数组。
    选取入度为 0 的数据,根据邻接表,减小依赖它的数据的入度。
    找出入度变为 0 的数据,重复第 2 步。
    直至所有数据的入度为 0,得到排序,如果还有数据的入度不为 0,说明图中存在环

    class Solution {
        // 一个node,就是一个课程
        // name是课程的编号
        // in是课程的入度
        public static class Node {
            public int name;
            public int in;
            public ArrayList<Node> nexts;
    
            public Node(int n) {
                name = n;
                in = 0;
                nexts = new ArrayList<>();
            }
        }
    
        public static boolean canFinish(int numCourses, int[][] prerequisites) {
            if (prerequisites == null || prerequisites.length == 0) {
                return true;
            }
            HashMap<Integer, Node> nodes = new HashMap<>();
            for (int[] arr : prerequisites) {
                int to = arr[0];
                int from = arr[1];
                if (!nodes.containsKey(to)) {
                    nodes.put(to, new Node(to));
                }
                if (!nodes.containsKey(from)) {
                    nodes.put(from, new Node(from));
                }
                Node t = nodes.get(to);
                Node f = nodes.get(from);
                f.nexts.add(t);
                t.in++;
            }
            int needPrerequisiteNums = nodes.size();
            Queue<Node> zeroInQueue = new LinkedList<>();
            for (Node node : nodes.values()) {
                if (node.in == 0) {
                    zeroInQueue.add(node);
                }
            }
            int count = 0;
            while (!zeroInQueue.isEmpty()) {
                Node cur = zeroInQueue.poll();
                count++;
                for (Node next : cur.nexts) {
                    if (--next.in == 0) {
                        zeroInQueue.add(next);
                    }
                }
            }
            return count == needPrerequisiteNums;
        }
    }
    
    image-20210623123609282

    拓扑排序问题的解决办法是主要是循环执行以下两步,直到不存在入度为0的顶点为止。

      1. 选择一个入度为0的顶点并输出之;
      1. 从网中删除此顶点及所有出边。

    循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,即无法完成所有任务;否则输出的顶点序列就是一种拓扑序列,即可以完成所有任务。

    // AOV 网的拓扑排序
    func canFinish(n int, pre [][]int) bool {
        in := make([]int, n)
        frees := make([][]int, n)
        next := make([]int, 0, n)
        for _, v := range pre {
            in[v[0]]++
            frees[v[1]] = append(frees[v[1]], v[0])
        }
        for i := 0; i < n; i++ {
            if in[i] == 0 {
                next = append(next, i)
            }
        }
        for i := 0; i != len(next); i++ {
            c := next[i]
            v := frees[c]
            for _, vv := range v {
                in[vv]--
                if in[vv] == 0 {
                    next = append(next, vv)
                }
            }
        }
        return len(next) == n
    }
    
    image-20210623123918452

    相关文章

      网友评论

          本文标题:LeetCode-207-课程表

          本文链接:https://www.haomeiwen.com/subject/enkbyltx.html