【LeetCode(Java) - 1136】平行课程

1、题目描述

在这里插入图片描述

2、解题思路

  把课程关系看成有向图,课程 A 指向课程 B,则 B 的入度加一。

  入度作为课程能否在本学期开课的依据。

  如果一个课程的入度为 0,说明现在没有该课程的先修课程,可以直接上了。否则不能直接上,必须等到先修课程上完才能上它。

  算法逻辑:

  1、针对给定的课程关系,统计课程的入度和课程的所有后继课程;

  2、初始时,入度就为 0 的课程就可以在第一学期上;

  3、每上完一学期,就把这学期上的课的后继课程的入度减一,然后统计减一后新的入度为 0 的课程,作为下学期的开课课程。

  4、经过 3 的循环,当最后一个学期结束,应该所有的课程入度都不大于 0,如果还存在某个课程入度大于 0,说明存在环,返回 -1。否则直接返回 3 的循环次数。

3、解题代码

class Solution {
    
    
    public int minimumSemesters(int N, int[][] relations) {
    
    
        // 每个课程都有不止一个后置课程
        Map<Integer, List<Integer>> courses = new HashMap<>();
        // inDegree[i] 表示课程 i 的入度
        int[] inDegree = new int[N + 1];
        for (int[] relation : relations) {
    
    
            int x = relation[0];
            int y = relation[1];
            inDegree[y]++;  // 课程 y 入度加一
            if (courses.containsKey(x)) {
    
    
                courses.get(x).add(y);
            } else {
    
    
                List<Integer> list = new ArrayList<>();
                list.add(y);
                courses.put(x, list);
            }
        }
        // 当前学期要学的课,即入度为 0 的课
        Set<Integer> curCourse = new HashSet<>();
        for (int i = 1; i < inDegree.length; i++) {
    
    
            if (inDegree[i] == 0) {
    
    
                curCourse.add(i);
            }
        }
        int term = 0;   // 学期数
        // 开始上课
        while (!curCourse.isEmpty()) {
    
    
            // 新学期开始了
            Set<Integer> nextCourse = new HashSet<>();  // 下学期要上的课
            // 开始上课,上课的内容就是把入度为 0 的课程的后置课程的入度减一,然后把新的入度为 0 的课程作为下学期的要上的课
            for (Integer cur : curCourse) {
    
    
                if (courses.get(cur) != null) {
    
    
                    List<Integer> y = courses.get(cur);  // 课程 cur 的所有后置课程
                    for (Integer id : y) {
    
    
                        // 课程 id 的入度减一
                        inDegree[id]--;
                        // 判断现在 id 是不是入度变为 0 了,如果是,则下学期要上它了
                        if (inDegree[id] == 0) {
    
    
                            nextCourse.add(id);
                        }
                    }
                }
            }
            // 上完课了,学期数加一
            term++;
            curCourse = nextCourse;
        }
        // 现在能上的已经上完了,如果还有课程入度大于 0,说明有环
        for (int i = 1; i < inDegree.length; i++) {
    
    
            if (inDegree[i] > 0) {
    
    
                return -1;
            }
        }
        return term;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_29051413/article/details/108519359
今日推荐