力扣 第210题
原题地址:
https://leetcode-cn.com/problems/course-schedule-ii/
分析:
本题是一道经典的「拓扑排序」问题。
给定一个包含n个节点的有向图G,我们给出它的节点编号的一种排列,如果满足:对于图G中的任意一条有向边(u,v),u在排列中都出现在v的前面。
那么称该排列是图G的 拓扑排序。可以得到两个结论:
1、如果图G中存在环,那么图G不存在拓扑排序。
2、如果图G是有向无环图,那么它的拓扑排序可能不止一种。极端的例子就是:如果图G值包含n个节点没有边,则任意编号排列都可以作为拓扑排序。
广度优先搜索排列:
思路:最先被放在拓扑排序中节点一定是 这个节点 没有任何入边。然后当一个节点被放在拓扑排序中后,这个节点指向的所有的入边个数都会减少一。直到所有的节点中没有入边的节点(此时可能会存在环)。
算法:使用一个队列来进行广度优先搜索。开始时,所有入度为0的节点都被放入队列中,它们就是可以作为拓扑排序最前面的节点,并且他们之间的相对顺序是无关紧要的。
在广度优先搜索的每一步中,我们取出队首的节点u:
(1)将u放在拓扑排序中;
(2)移除u的所有出边,也就是将u的所有相邻节点的入度减少1。如果相邻节点v的入度变为0,那么我们将v放入队列中。
最后如果拓扑排序中包含这n个节点,则这个就是我们要找的拓扑排序。否则说明存在环。
class Solution { private: vector<vector<int>> edges; vector<int> indeg; vector<int> result; public: vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) { edges.resize(numCourses); indeg.resize(numCourses); for(const auto& info : prerequisites) { ++indeg[info[0]]; edges[info[1]].push_back(info[0]); } queue<int> q; for (int i = 0; i < numCourses; ++i) { if (indeg[i] == 0) { q.push(i); } } while(!q.empty()) { int u = q.front(); q.pop(); result.push_back(u); for (int v : edges[u]) { --indeg[v]; if (indeg[v] == 0) { q.push(v); } } } if (result.size() != numCourses) { return {}; } return result; } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通