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

问题介绍

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

课程表问题

在这里插入图片描述

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

解法:广度优先

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

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

class Solution {
private:
    vector<vector<int>> edges;//存储有向图
    vector<int> in;//存储每个节点的入度
    vector<int> ans;//返回符合条件的拓扑排序
public:
    vector<int> findOrder(int numCourses, vector<vector<int>>& 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<int> q;
        //将所有入度为0的节点入队
        for(int i=0;i<numCourses;++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数组,用一个数字来加法记录,可以节省空间;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值