拓扑排序 + 力扣课表问题

拓扑排序(详解,拓扑排序看这一片就够了)

首先,拓扑排序是利用BFS算法来实现的,要说到BFS算法在图中应用,拓扑排序首屈一指
本篇文章用一道leetcode上经典的题目(207.课程表)来讲解拓扑排序,题目链接:https://leetcode.cn/problems/course-schedule/
在这里插入图片描述

第一步,你需要构建出拓扑排序最基础的图表出来,就像要先学A这门课程的话就要先学B的话,那么图的表示就是B->A,以此类推。
第二步,你需要统计出图中所有点的入度,如果学A这么课程要先学B1,B2,B3这三门课那么A的入度就为3,以此类推。
基础工作做好之后就是利用BFS的思想去解题了。
你首先要把入度为0的点全部放在queue容器中(或者其他的容器中),然后让queue中第一个元素的后续节点的入度全部减1,判断入度是否为0,如果减1之后为0,就把这个节点加入进queue容器中,否则继续重复同样的操作,直至queue容器为空。在此期间,你需要统计好一共有多少元素加入了queue这个容器中,以此来和总共的元素作比较。
以上就是拓扑排序的基本流程了,具体怎么利用还要依情况而定。
像上面这道题目,统计好一共有多少元素加入了queue这个容器中之后,你需要判断在这个数是否和总数目相等,如果相等,则返回true,反之则反之。
话不多说,上代码

class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
        unordered_map<int, vector<int>> pre;//建立图所需的容器
        vector<int> in(numCourses);//建入度所需的容器
        for (int i = 0; i < prerequisites.size(); i++)
        {
            pre[prerequisites[i][1]].push_back(prerequisites[i][0]);//建表
            in[prerequisites[i][0]]++;//统计入度
        }
        queue<int>q;
        for(int i = 0; i < numCourses; i++)
        {
            if(in[i] == 0)
            {
                q.push(i);//初始工作
            }
        }
        int cnt = 0;
        while(!q.empty())
        {
            auto cur = q.front();
            q.pop();
            cnt++; //统计步数,也就是有多少元素加入过queue中
            for(auto x : pre[cur])
            {
                if(--in[x] == 0)//为0则加入queue中
                {
                    q.push(x);
                }
            }    
        }
        return cnt == numCourses;
    }
};

当然,对于力扣第210题课程表2,https://leetcode.cn/problems/course-schedule-ii/来说,大体的步骤都是一样的,只要设置一个存储最终答案的vector容器即可,并把step那个步骤换成容器的push操作即可,代码如下

vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
        vector<int>result;
        unordered_map<int, vector<int>>pre;
        vector<int>in(numCourses);
        for(int i = 0; i < prerequisites.size(); i++)
        {
            in[prerequisites[i][0]]++;
            pre[prerequisites[i][1]].push_back(prerequisites[i][0]);
        }
        queue<int>q;
        for(int i = 0; i < in.size(); i++)
        {
            if(in[i] == 0)
            {
                q.push(i);
            }
        }
        while(!q.empty())
        {
            int cur = q.front();
            q.pop();
            result.push_back(cur);
            for(int i =0; i < pre[cur].size(); i++)
            {
                if(--in[pre[cur][i]] == 0)
                {
                    q.push(pre[cur][i]);
                }
            }
        }
        if(result.size() < numCourses)
            return {};
        else 
            return result;
    }

以上是写题过程中的小小记录,希望大家指正。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值