LeetCode热题--207. 课程表--中等

1. 题目

你这个学期必须选修 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 。这是可能的。

示例 2:

输入:numCourses = 2, prerequisites = [[1,0],[0,1]]

输出:false

解释:总共有 2 门课程。学习课程 1 之前,你需要先完成​课程 0 ;并且学习课程 0 之前,你还应先完成课程 1 。这是不可能的。

2. 题解

java 复制代码
class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        // 入度数组,用于记录每门课程的入度
        int[] inDegree = new int[numCourses];
        // 邻接表,存储每门课程的后续课程
        List<List<Integer>> adjList = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) {
            adjList.add(new ArrayList<>());
        }

        // 计算每门课程的入度,并构建邻接表
        for (int[] prerequisite : prerequisites) {
            int course = prerequisite[0];
            int preCourse = prerequisite[1];
            inDegree[course]++;
            adjList.get(preCourse).add(course);
        }

        // 存储入度为 0 的课程的队列
        Queue<Integer> queue = new LinkedList<>();
        for (int i = 0; i < numCourses; i++) {
            if (inDegree[i] == 0) {
                queue.offer(i);
            }
        }

        // 记录已完成课程的数量
        int count = 0;
        while (!queue.isEmpty()) {
            int selectedCourse = queue.poll();
            count++;
            // 获取当前课程的后续课程列表
            List<Integer> nextCourses = adjList.get(selectedCourse);
            for (int nextCourse : nextCourses) {
                // 后续课程的入度减 1
                inDegree[nextCourse]--;
                if (inDegree[nextCourse] == 0) {
                    queue.offer(nextCourse);
                }
            }
        }

        // 如果已完成课程的数量等于总课程数,则可以完成所有课程
        return count == numCourses;
    }
}

3. 解析

出自:「图解」拓扑排序 | 课程表问题

int[] inDegree = new int[numCourses];: 初始化一个数组来记录每门课程的入度,表示从其他课程到当前课程的箭头数量。

List<List> adjList = new ArrayList<>();: 创建一个邻接表(Adjacency List)用于存储每门课程的后续课程。这是一个列表的列表,其中每个内部列表表示一门课程及其所有的后续课程。

for (int i = 0; i < numCourses; i++) { adjList.add(new ArrayList<>()); }: 初始化邻接表中的空列表以匹配每门课程的数量。

4-7: 遍历所有预备课程,计算每个课程的入度并构建邻接表。对于每一对预备课程(preCourse, course),将course的入度加1,并将preCourse添加到course的后续课程列表中。

Queue queue = new LinkedList<>();: 创建一个队列来存储所有入度为0的课程。这是因为这些课程没有先决条件(即它们是可以直接选修的课程)。

9-15: 遍历所有的课程,将那些入度为0的课程添加到队列中。

int count = 0;: 初始化一个计数器来记录已经完成的课程数量。

17-24: 开始主循环,直到队列为空(即没有任何可以选择的课程了)或者已完成的课程数量等于总课程数(表示所有课程都可以完成)。在每一轮中,从队列中取出一门课程进行处理(增加计数器并将其后续课程的入度减1),如果任何一个后续课程的入度降为0(即没有先决条件了),就将它添加到队列中。

25: 最后返回已完成课程数量是否等于总课程数来判断能否完成所有课程。

这段代码是拓扑排序的一种实现方式,用于解决课程表问题(Schedule of Courses),如果能通过所有的入度为0的课程,那么就可以完成所有课程。

相关推荐
吟安安安安4 分钟前
适合短期冲刺的学习工作流(针对算法)
学习·算法
科研前沿9 分钟前
什么是时空融合技术?
大数据·人工智能·数码相机·算法·重构·空间计算
AI科技星14 分钟前
全域数学本源公理:0、1、∞ 三者核心关系 (典籍定稿版)
人工智能·算法·数学建模·数据挖掘·量子计算
AI科技星19 分钟前
全域数学·第卷:场计算机卷(场空间计算机)【乖乖数学】
java·开发语言·人工智能·算法·机器学习·数学建模·数据挖掘
Deepoch21 分钟前
数学模型驱动:Deepoc 低幻觉数学大模型助力发动机全周期智能优化
人工智能·算法·机器学习·deepoc·数学大模型·低幻觉
嘻嘻哈哈樱桃30 分钟前
牛客经典101题解题集--贪心算法+模拟
java·python·算法·贪心算法
AKDreamer_HeXY30 分钟前
QOJ 12255 - 36 Puzzle 题解
数据结构·c++·数学·算法·icpc·qoj
AI科技星39 分钟前
《全域数学》第一部 数术本源 第三卷 代数原本第14篇 附录二 猜想证明【乖乖数学】
人工智能·算法·数学建模·数据挖掘·量子计算
Wect1 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·typescript
憨波个1 小时前
【说话人日志】DOVER-Lap:overlap-aware diarization 输出融合算法
人工智能·深度学习·算法·音频·语音识别