算法日常・每日刷题--<BFS拓扑排序>4

LCR 113. 课程表 II - 力扣(LeetCde)

题目理解

总共有 numCourses 门课,编号0 ~ numCourses‑1。 prerequisites[i] = [a,b]:学 a 课,必须先学 b 课。

要求返回任意一个合法上课顺序。

  • 存在拓扑序列(无环):返回上课顺序数组
  • 图有环(循环依赖,课学不完):返回空数组

和课程表 I 区别:课程表 I 只需要判断 true/false;本题需要把拓扑排序的序列输出出来。

核心思路 BFS 拓扑排序

  1. 建图(邻接表) :b → a,b 上完之后才可以上 a;统计每门课的入度(还有几门先修没上完)
  2. 入度为 0 全部入队列:不需要先修、可以直接学的课程
  3. BFS 遍历
    • 取出队头课程,加入结果集合(代表这门课已经上完)
    • 把它所有后继课程入度减一(消除这门课带来的依赖)
    • 如果后继课程入度变成 0,说明它的全部先修课完成,入队列
  4. 最后判断
    • 如果结果数组长度等于总课程数:全部课都上完,直接返回结果
    • 长度不够:说明有环,返回空数组
cpp 复制代码
class Solution {
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        vector<vector<int>> edges(numCourses); // 临接表
        vector<int> in(numCourses,0);

        // 构建图
        for (auto e : prerequisites) {
            int a = e[0];
            int b = e[1];
            edges[b].push_back(a);
            in[a]++;
        }

        vector<int> ret;
        queue<int> q;
        for (int i = 0; i < numCourses; i++) {
            if (in[i] == 0) {
                q.push(i);
            }
        }

        while (q.size()) {
            int a = q.front();
            q.pop();
            ret.push_back(a);
            for (auto next : edges[a]) {
                // 将有关边的入度--
                in[next]--;
                if (in[next] == 0) {
                    q.push(next);
                }
            }
        }
        if (ret.size() == numCourses)
            return ret;
        else
            return {};
    }
};
相关推荐
HZY1618yzh1 分钟前
下一代编程语言出炉
c++·算法
CoderYanger8 分钟前
A.每日一题:856. 括号的分数
java·程序人生·算法·leetcode·面试·职场和发展·学习方法
kiracrimson22 分钟前
选择排序与快速排序:一次选极值,一次分区间
算法·排序算法
All for pursuit.41 分钟前
【动态规划-8】152.乘积最大子数组
数据结构·c++·算法·leetcode·动态规划
信奥卷王44 分钟前
[GESP202512 六级] 路径覆盖
数据结构·算法
Lazionr1 小时前
手撕 unordered_set 和 unordered_map,剖析哈希表底层实现
c++·算法
0+1111 小时前
算法 --归并排序
数据结构·算法·排序算法
Run_Teenage1 小时前
算法:树的重心、树的直径
算法
专注仿真1 小时前
高代价计算后置:探测、交战、毁伤三条链路的统一设计哲学
算法·探测·毁伤
xie0510_1 小时前
Any类简要实现
开发语言·c++·算法