【刷题日记】leetcode207-课程表

125 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

题目描述

image.png

题目释义

  • 课程总数为n,编号从0,n-1;

  • 依赖条件二维数组,每个数组代表一个依赖条件,即a1->a0; 这个是个典型的拓扑排序,什么是拓扑排序呢?对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边<u,v>∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。 简单来说就是图中的各个顶点之间都是有向的,比如A->B,则意味着A在B之前。也可以由此延伸出入度和出度的概念。入度是指向本顶点的箭头数,出度是指从本顶点向外发出的箭头数。 拓扑排序就是把满足这样条件的图,从入度为0的顶点A开始,删除从A发出的箭头,即将B、D入度在原来的基础上减1。然后循环。依次将入度变为0的顶点进行排序,就得到了拓扑排序。

image.png

如图是一个有向无环图,它的拓扑排序应该是A->D->B->F

解题思路

反观这个题,题解思路就很清晰明了了。其中重要的数据处理就是要计算每个顶点的入度,然后从入度为0的开始消除箭头。循环往复,最后如果循环次数不等于课程数,直接返回false。 那接下来就一起来coding吧!

代码实现

public static boolean canFinish(int numCourses, int[][] prerequisites) {
    //使用数组来装所有顶点的连接顶点
    //角标为课程num,角标对应的数组为该课程对应的上级连接课程,换句话说,这个数组的size就是入度数
    List<List<Integer>> inInfoList = new ArrayList<>(numCourses);
    //初始化这个数组
    for (int i =0;i<numCourses;i++){
        inInfoList.add(new ArrayList<>());
    }
    //二维数组转成上述list,因为依赖关系是prerequisite[1]->prerequisite[0],所以数组中的第二个元素是第一个元素的上级连接课程
    for (int[] prerequisite : prerequisites) {
        inInfoList.get(prerequisite[0]).add(prerequisite[1]);
    }
    //用栈存储入度为0的课程num
    Stack<Integer> passIndex = new Stack<>();
    for (int i=0;i<inInfoList.size();i++){
        if (inInfoList.isEmpty()){
            passIndex.add(i);
        }
    }
    //循环计数器
    int count = 0;
    //循环截止条件:栈中不存在入度为0的课程num了
    while (!passIndex.isEmpty()){
        //弹出栈-栈顶入度为0的课程num
        Integer currentNum = passIndex.pop();
        //循环次数加1
        count ++;
        for (int i=0;i<inInfoList.size();i++){
            List<Integer> integers = inInfoList.get(i);
            //如果连接课程为空,说明之前已经放入过了栈中,直接continue
            if (integers.size() == 0){
                continue;
            }
            //将当前课程从上级连接课程中去掉
            integers.remove(currentNum);
            //如果剩余连接课程size为0,则直接放入栈中
            if (integers.size() == 0){
                passIndex.push(i);
            }
        }
    }
    //如果循环次数=课程数,则表示所有课程都满足了入度为0的条件,返回true,否则为false
    return count == numCourses;
}