力扣 第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;
    }
};
复制代码

 

posted @   小海哥哥de  阅读(171)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示