210.课程表Ⅱ

1.题目描述

现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。

  • 例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。

返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。

示例 1:

输入:numCourses = 2, prerequisites = [[1,0]]
输出:[0,1]
解释:总共有 2 门课程。要学习课程 1,你需要先完成课程 0。因此,正确的课程顺序为 [0,1] 。

示例 2:

输入:numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]
输出:[0,2,1,3]
解释:总共有 4 门课程。要学习课程 3,你应该先完成课程 1 和课程 2。并且课程 1 和课程 2 都应该排在课程 0 之后。
因此,一个正确的课程顺序是 [0,1,2,3] 。另一个正确的排序是 [0,2,1,3]

示例 3:

输入:numCourses = 1, prerequisites = []
输出:[0]
提示:
  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= numCourses * (numCourses - 1)
  • prerequisites[i].length == 2
  • 0 <= ai, bi < numCourses
  • ai != bi
  • 所有[ai, bi] 互不相同

2.解题思路

本题思路基本与207.课程表Ⅰ类似,但是inDegree是可以进行优化的,我们不必存储每门课它所有的先修课程,例如(0,1),(0,2)表示学习0之前要学习1,2两门课,之前我们的inDegree[0] = [1,2],其实只需要使用一个整数存储这门课有几门先修课就行,例如inDegree[0] = 2,表明0这门课有两门先修课,然后从inDegree值为0的课程开始广度优先遍历,每次访问的结点,就把以它为key的inDegree的值-1,当这个值为0时,就表明它的所有先修课都已经学习了,可以把它加入到队列,再以它开始学习它的后序课程。这样最终res中就能记录一个符合题意的学习顺序,如果存在环形依赖,就无法学完全部的课程,返回空数组即可

3.代码实现

class Solution {
    public int[] findOrder(int numCourses, int[][] prerequisites) {
        int[] res = new int[numCourses];
        int p = 0;
        //借助一个队列实现广度优先遍历
        boolean[] learned = new boolean[numCourses];
        Map inDegree = new HashMap<>();
        Map> outDegree = new HashMap<>();
        //初始化map 其中inDegree保存每门课程的先修课程
        //outDegree 保存每门课程的后序课程
        for (int i = 0; i < numCourses; i++) {
            inDegree.put(i,0);
            outDegree.put(i,new ArrayList<>());
        }
        //遍历prerequisites给map赋值
        for (int i = 0; i < prerequisites.length; i++) {
            int cur = prerequisites[i][0];
            int pre = prerequisites[i][1];
            List outs = outDegree.get(pre);
            outs.add(cur);
            outDegree.put(pre,outs);
            inDegree.put(cur,inDegree.get(cur) + 1);
        }
        //把入度为0的结点入队
        Queue queue = new LinkedList<>();
        for (Integer i : inDegree.keySet()) {
            if (inDegree.get(i) == 0) {
                queue.offer(i);
            }
        }
        while (!queue.isEmpty()) {
            Integer cur = queue.poll();
            learned[cur] = true;
            res[p++] = cur;
            for (int x : outDegree.get(cur)) {
                int cnt = inDegree.get(x);
                cnt -= 1;
                if (cnt == 0) {
                    queue.offer(x);
                } else {
                    inDegree.put(x,cnt);
                }
            }
        }
        for (int i = 0; i < numCourses; i++) {
            if (!learned[i]) {
                return new int[]{};
            }
        }
        return res;
    }
}

你可能感兴趣的:(算法刷题,算法,广度优先搜索,图,java)