栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

14.算法——拓扑排序(课程表问题210,207)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

14.算法——拓扑排序(课程表问题210,207)

问题介绍

我理解主要是这么一个图论问题,在一群节点中,每个节点都有自己的入度和出度,一条有向边的方向可以理解为先后问题。而后我们对这些节点进行排序,保证先访问入度为0的节点。
主要是看有没有环的问题。
这样讲可能有些玄幻,举个例子。

课程表问题

在这个题目中,数组pre的first代表要想修1必须修0,即一条从0到1的有向边。

解法:广度优先

队列表示访问,入度为0的先访问(出队),访问到某一个节点之后,与其相邻节点的入度减一,如果减一之后出现新入度为0的节点,继续入队。

看最后访问数组的size和原数组是否相等

class Solution {
private:
    vector> edges;//存储有向图
    vector in;//存储每个节点的入度
    vector ans;//返回符合条件的拓扑排序
public:
    vector findOrder(int numCourses, vector>& prerequisites) 
    {
        edges.resize(numCourses);
        in.resize(numCourses);
        //用edges存储每个节点的出度(这样就知道与该节点相邻的所有节点),用in存储每个节点入度数目
        for(const auto& info:prerequisites)
        {
            edges[info[1]].push_back(info[0]);
            ++in[info[0]];//被指向的节点入度+1
        }
        queue q;
        //将所有入度为0的节点入队
        for(int i=0;i
            if(in[i]==0) q.push(i);
        }
        //每次取出队首元素,放入ans,并将所有与之相邻节点入度-1
        while(!q.empty())
        {
            int first=q.front();
            q.pop();
            ans.emplace_back(first);
            //遍历该节点所有出度,将相邻节点入度-1.如果此时新出现了入度为0的节点,入队
            for(int v:edges[first])
            {
                --in[v];
                if(in[v]==0) q.push(v);
            }
        }
        //如果拓扑排序size小于原数组,则存在环
        if(ans.size()!=numCourses) return {};
        return ans;
        
    }
};

至于深度优先,作者认为广度优先更符合人的正常思维一些,深度优先有些逆向思维,在面试的环境下掌握广度优先解即可。

最后,第207题,可作同解,也可略作优化,因为他只要t/f。我们可以省去ans数组,用一个数字来加法记录,可以节省空间;

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/876397.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号