• 207. Courses Schedule via Java


    课程安排本质上是一道拓扑排序题。

    拓扑排序即位找出有向图的顶点的线性排序,使得对于从顶点 u 到顶点{displaystyle v}的每个有向边{displaystyle uv} u 在排序中都在{displaystyle v}之前。

    性质:

    当且仅当一个有向图没有环(DAG)才有可能有拓扑排序。

    任何DAG具有至少一个拓扑排序,并且已知这些算法用于在线性时间内构建任何DAG的拓扑排序。

    在图论中,由一个有向无环图的顶点组成的序列,当且仅当满足下列条件时,称为该图的一个拓扑排序(英語:Topological sorting):

    1. 每个顶点出现且只出现一次;
    2. 若A在序列中排在B的前面,则在图中不存在从B到A的路径。

    卡恩算法:

    • 假设L是存放结果的列表,先找到那些入度为零的节点,把这些节点放到L中,因为这些节点没有任何的父节点。
    • 然后把与这些节点相连的边从图中去掉,同时更新所有节点的入度,再寻找图中的入度为零的节点。
    • 对于新找到的这些入度为零的节点来说,他们的父节点已经都在L中了,所以也可以放入L。
    • 重复上述操作,直到找不到入度为零的节点。
    • 如果此时L中的元素个数和节点总数相同,说明排序完成;如果L中的元素个数和节点总数不同,说明原图中存在环,无法进行拓扑排序。

    L ← 包含已排序的元素的空列表
    S ← 没有进入边的节点(入度为零的节点)的集合
    当 S 非空时:
        将节点n从S移走
        将n加到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
    如 图有边 则:
        return error   (图至少有一个环)
    否则: 
        return L   (以拓扑排序的顺序)

    public boolean canFinish(int numCourses, int[][] prerequisites) {
            //Topological Order
            //record degree&edges
            //then remove each node which in-degree is 0
            //if the final number of node we've already removed is equal to numCourses, then return true 
            List<Integer>[] adj = new List[numCourses];
            for (int i = 0; i < numCourses; i++)
                adj[i] = new ArrayList<Integer>();
            int[] indegree = new int[numCourses];
            Queue<Integer> readyCourses = new LinkedList();
            int finishCount = 0;
            for (int i = 0; i < prerequisites.length; i++) {
                int curCourse = prerequisites[i][0];
                int preCourse = prerequisites[i][1];
                adj[preCourse].add(curCourse);
                indegree[curCourse]++;
            }
            for (int i = 0; i < numCourses; i++) {
                if (indegree[i] == 0)
                    readyCourses.offer(i);
            }
            while (!readyCourses.isEmpty()) {
                int course = readyCourses.poll(); 
                finishCount++;
                for (int nextCourse : adj[course]) {
                    indegree[nextCourse]--;
                    if (indegree[nextCourse] == 0)
                        readyCourses.offer(nextCourse); 
                }
            }
            return finishCount == numCourses;
        }

    时间复杂度

    空间复杂度

    留待以后

  • 相关阅读:
    VCSA 6.5 升级 VCSA 6.7
    使用再生龙Clonezilla备份还原Linux系统
    gulp前端自动化构建工具学习笔记(mac)
    Echarts基本图表的学习笔记
    jQuery中$.ajax()用法
    jQuery实现淡入淡出轮播图带左右按钮及下方小圆点
    js解析XMl文件,兼容IE、Firefox、谷歌
    HTML<marquee>标签实现滚动公告通知、广告的效果
    画太极
    让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
  • 原文地址:https://www.cnblogs.com/zg1005/p/11882272.html
Copyright © 2020-2023  润新知