【图论】Leetcode 207. 课程表【中等】

课程表

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。

  • 例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
    请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。

示例1:

输入: numCourses = 2, prerequisites = [[1,0]]
输出: true
解释:总共有 2 门课程。学习课程 1 之前,你需要完成课程 0 。这是可能的。

解题思路

  • 这个问题可以转化为判断有向图中是否存在环的问题,如果存在环,
    则说明存在课程之间的循环依赖,无法完成所有课程的学习;
    如果不存在环,则说明不存在循环依赖,可以完成所有课程的学习。

  • 1、使用拓扑排序来判断是否存在环,即是否可以完成所有课程的学习。

  • 2、使用邻接表来表示课程之间的先修关系。

  • 3、统计每门课程的入度,入度为0表示没有先修课程。

  • 4、将入度为0的课程加入队列,并从队列中依次弹出课程,将其后继课程的入度减1。

  • 5、如果存在环,即存在入度为0的课程无法全部弹出,则说明无法完成所有课程的学习,返回false;否则返回true。

Java实现

广度优先搜索(BFS)实现

public class CourseSchedule {

    public boolean canFinish(int numCourses, int[][] prerequisites) {
        // 构建有向图和入度数组
        Map<Integer, List<Integer>> graph = new HashMap<>();
        int[] indegree = new int[numCourses];
        for (int[] prereq : prerequisites) {
            int course = prereq[0];
            int prereqCourse = prereq[1];
            graph.putIfAbsent(prereqCourse, new ArrayList<>());
            graph.get(prereqCourse).add(course);
            indegree[course]++;
        }
        
        // 将入度为 0 的节点加入队列中
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if (indegree[i] == 0) {
                queue.offer(i);
            }
        }
        
        // 使用广度优先搜索进行拓扑排序
        int visited = 0;
        while (!queue.isEmpty()) {
            int course = queue.poll();
            visited++;
            List<Integer> neighbors = graph.getOrDefault(course, new ArrayList<>());
            for (int neighbor : neighbors) {
                indegree[neighbor]--;
                if (indegree[neighbor] == 0) {
                    queue.offer(neighbor);
                }
            }
        }
        
        return visited == numCourses;
    }

    public static void main(String[] args) {
        CourseSchedule scheduler = new CourseSchedule();
        int numCourses = 4;
//        int[][] prerequisites = {{1, 0}, {2, 1}, {3, 2}, {3, 1}};
        int[][] prerequisites = {{1, 0}, {2, 1}, {3, 2}, {1, 3}};
        System.out.println(scheduler.canFinish(numCourses, prerequisites));
    }
}

时间空间复杂度

  • 时间复杂度:O(V + E),其中 V 表示课程数量,E 表示先修课程的数量,因为需要构建邻接表和统计入度,以及进行BFS拓扑排序。

  • 空间复杂度:O(V + E),其中 V 表示课程数量,E 表示先修课程的数量,因为需要存储邻接表和入度数组。

相关推荐

  1. Leetcode 207. 课程表中等

    2024-04-10 06:56:01       39 阅读
  2. Leetcode 200. 岛屿数量【中等

    2024-04-10 06:56:01       50 阅读
  3. LeetCode热题100】【课程表

    2024-04-10 06:56:01       151 阅读
  4. LeetCode207、210 课程表 dfs 拓扑排序)

    2024-04-10 06:56:01       41 阅读
  5. leetcode 207.课程表

    2024-04-10 06:56:01       29 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-10 06:56:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-10 06:56:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-10 06:56:01       87 阅读
  4. Python语言-面向对象

    2024-04-10 06:56:01       96 阅读

热门阅读

  1. [尚硅谷flink学习笔记] 实战案例TopN 问题

    2024-04-10 06:56:01       31 阅读
  2. 同一个pdf在windows和linux中的页数不一样

    2024-04-10 06:56:01       40 阅读
  3. 前端小白的学习之路(Vue2 二)

    2024-04-10 06:56:01       42 阅读
  4. vite项目如何安装element

    2024-04-10 06:56:01       42 阅读
  5. yum和配置yum源

    2024-04-10 06:56:01       35 阅读
  6. 1215: 【C4】【搜索】【回溯】数字全排列

    2024-04-10 06:56:01       37 阅读
  7. opencv支持的一些计算光流的算法

    2024-04-10 06:56:01       40 阅读