20200805:Java拓扑排序实现力扣207课程表

力扣207:课程表

  • 题目
  • 思路与算法
  • 代码实现

题目

题目链接:课程表
你这个学期必须选修 numCourse 门课程,记为 0 到 numCourse-1 。

在选修某些课程之前需要一些先修课程。 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示他们:[0,1]

给定课程总量以及它们的先决条件,请你判断是否可能完成所有课程的学习?

20200805:Java拓扑排序实现力扣207课程表_第1张图片

思路与算法

  1. 注意该题示例2给到的提示,即意思是构成的图不能有环,可能会联想到最短路径系列的算法,迪杰斯拉,贝尔曼福特之类的算法,但本题只要求判断正误,跟最短路径关系不大,仔细读题发现就是一道拓扑排序的问题,给定的所谓前置必修课程即为入点,一切都已经注释好了,不可能看不懂。

代码实现

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {

        // 注意pre数组的每一维的前后关系别弄反,后者是前者的前置依赖必修课。
        int[] beforeClassCounts = new int[numCourses]; 
        List<List<Integer>> dependencyLists = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            dependencyLists.add(new ArrayList<>());
        }
        Queue<Integer> queue = new LinkedList<Integer>();
        // 将每个课程的入度记录下来
        // 将每个节点的 以该节点为前置依赖必修课的课程记录下来
        for (int[] pre : prerequisites) {
            beforeClassCounts[pre[0]]++;
            dependencyLists.get(pre[1]).add(pre[0]);
        }
        
        // 将入度为0的课程直接入队,获取以该课程为前置必修课的课程列表,遍历这些列表,将其入度-1。
        for (int i = 0;i < numCourses; i++) {
            if (beforeClassCounts[i] == 0) {
                queue.add(i);
            }
        }
        // 并进行判断,若这些列表中的课程此时的入度为1,即这些课程此时可以修了,将其入队。
        while (!queue.isEmpty()){
            int FinishedCourse = queue.poll();
            // numCourses--; 放前后都可以
            for (int cur : dependencyLists.get(FinishedCourse)) {
                if ( --beforeClassCounts[cur] == 0) {
                    queue.add(cur);
                }
            }
            numCourses--;
        }
        // 因为入队的课程已经修了,总修课程数目-1。
        //当没有入度为1的课程时判断此时的已修课程数目与必修总课程numCourse的大小关系,为0则true,否则为false。
        return numCourses == 0;

    }
}

你可能感兴趣的:(leetcode学习记录篇)