【优选算法专栏】专题十八:BFS解决拓扑排序(一)

本专栏内容为:算法学习专栏,分为优选算法专栏,贪心算法专栏,动态规划专栏以及递归,搜索与回溯算法专栏四部分。 通过本专栏的深入学习,你可以了解并掌握算法。

💓博主csdn个人主页:小小unicorn
⏩专栏分类:算法从入门到精通
🚚代码仓库:小小unicorn的代码仓库🚚
🌹🌹🌹关注我带你学习编程知识

专题十八

  • 课程表
    • 算法原理:
  • 课程表 II
    • 算法原理:
  • 总结:

课程表

你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。

在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。

例如,先修课程对 [0, 1] 表示:想要学习课程 0 ,你需要先完成课程 1 。
请你判断是否可能完成所有课程的学习?如果可以,返回 true ;否则,返回 false 。

在这里插入图片描述

算法原理:

本题题意要先搞懂,举个例子:
在这里插入图片描述
假设传入的这个数组,以[1,0]来说,它的意思就是要想先修1,就必须先学习0这门课程,依次内推。想这个我们可以画个箭头好理解:0->1 意思就是学1要先学0;

分析到这,我们就可以把这个数组抽象出来:
在这里插入图片描述
这个图是不是很熟悉,这不就是我们的有向图吗?

看一下题目问的啥,问能否修完?那这问题的本质不就是给这个图能否拓扑排序,或者问这个图是不是有环.

分析到这,其实就可以动手写代码了,但是我们前言末尾说到过,实现拓扑排序的前提是要建图。我们先打一下理论基础,看如何建图:

首先如何灵活建图的前提我们要合理用我们的容器。
其次要看数据的稠密也就是数据量,我们通常有两种办法:

  1. 邻接矩阵
  2. 邻接表
    邻接矩阵市面上书籍讲的很多,这里我们采用邻接表的形式。
    什么是邻接表呢?
    在这里插入图片描述
    以刚才例子为例,我们把每个位置相连的点都放在一排,所形成的这个表就是邻接表。

可能有人好奇,那我们岂不是要实现一个链表,才能形成上面的对应关系,其实不然,我们用数组就可以模拟代替链表。

接下来我们可以选择合适的容器,也就是代码如何实现,这里我们给出两种:

  1. vector
    我们在vector里嵌套一个vector:
vector<vector<int>> edge;//edge边的意思

为什么二维数组就可以呢?
在这里插入图片描述
我们让其下标具有对应关系,咱们得邻接表不就出来了。

  1. 哈希表

用哈希表来实现邻接表:

unordered_map<int,vector<int>> edge;
unordered_map<string,vector<string>> edge;

在这里插入图片描述
用哈希来反映映射也是可以的。

代码实现:

class Solution 
{
public:
    bool canFinish(int n, vector<vector<int>>& prerequisites) 
    {
        //1.准备工作
        unordered_map<int,vector<int>> edge;//邻接表存图
        //vector<vector<int>> edge(n);
        vector<int> in(n);//用来标记入度

        //2.建图
        for(auto& e:prerequisites)
        {
            int a=e[0],b=e[1];  //b->a的一条边
            //拿到b的这条边
            //把a插入到b的后面
            edge[b].push_back(a);
            //有一条边指向a了,a入度++
            in[a]++;
        }

        //3.拓扑排序
        queue<int> q;
        //(1)把所有入度为0的点加入到队列中
        for(int i=0;i<n;i++)
        {
            //入度为0
            if(in[i]==0)
            //加入队列
            q.push(i);
        }
        //(2)bfs
        while(q.size())
        {
            int t=q.front();
            q.pop();
            //拿出点后,要把这个点相连的边删掉
            for(int a:edge[t])
            {
                //入度--
                in[a]--;
                //如果入度为0,进入队列
                if(in[a]==0)
                q.push(a);
            }
        }
        //4.判断是否有环
        for(int i=0;i<n;i++)
        {
            if(in[i])
            return false;
        } 
        return true;
    }
};

课程表 II

现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。

例如,想要学习课程 0 ,你需要先完成课程 1 ,我们用一个匹配来表示:[0,1] 。
返回你为了学完所有课程所安排的学习顺序。可能会有多个正确的顺序,你只要返回 任意一种 就可以了。如果不可能完成所有课程,返回 一个空数组 。
在这里插入图片描述

算法原理:

本题跟课程表一模一样,只是返回的结果不一样,本题要返回一个序列,所以我们用一个数组统计一下信息即可。

代码实现:

class Solution 
{
public:
    vector<int> findOrder(int n, vector<vector<int>>& prerequisites) 
    {
        
        //1.准备工作
        vector<vector<int>> edge(n);//用来储存图
        //unordered_map<int,vector<int>> edge;
        vector<int> in(n);//用来标记入度

        //2.建图
        for(auto& e:prerequisites)
        {
            int a=e[0],b=e[1];  //b->a的一条边
            //把a插入到b的后面
            edge[b].push_back(a);
            //
            in[a]++;
        }

        //3.拓扑排序
        queue<int> q;
        vector<int> ret;
        //(1)把所有入度为0的点加入到队列中
        for(int i=0;i<n;i++)
        {
            //入度为0
            if(in[i]==0)
            //加入队列
            q.push(i);
        }
        //(2)bfs
        while(q.size())
        {
            int t=q.front();
            q.pop();
            ret.push_back(t);
            for(int a:edge[t])
            {
                //入度--
                in[a]--;
                //如果入度为0,进入队列
                if(in[a]==0)
                q.push(a);
            }
        }
        //4.判断是否有环
        if(ret.size()==n)return ret;
        else return {};
    }
};

总结:

其实用代码建图很简单,对于代码其实也就两三行的事情:

  1. 准备工作
//数组模拟
vector<vector<int>> edge(n)//n是大小
//哈希表模拟
unordered_map<int,vector<int>> edge;
//入度
vector<int> in(n);
  1. 建图
for(auto& e:prerequisites)
{
	int e[0]=a,e[1]=b;  b->a;
	//找到b这条边
	e[b].push_back(a);
	//有一条边指向了a
	//a入度++
	in[a]++;
}
  1. 拓扑排序

排序就根据前言分析的步骤实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/530380.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【第七篇】使用BurpSuite进行主动、被动扫描和主动、被动爬虫

文章目录 前言主动扫描被动扫描主动爬虫被动爬虫前言 Burp Scanner 既可以用作全自动扫描仪,也可以用作增强手动测试工作流程的强大手段。 扫描网站涉及两个阶段: 抓取内容和功能: Burp Scanner 首先在目标站点周围导航,密切反映真实用户的行为。它对站点的结构和内容以及…

STM32F4XX软件I2C驱动MPU6050

MPU6050 一、简介 MPU6050是一款6轴姿态传感器&#xff0c;可以测量芯片自身X、Y、Z轴的加速度、角速度参数&#xff0c;通过数据融合&#xff0c;可进一步得到姿态角&#xff0c;常应用于平衡车、飞行器等需要检测自身姿态的场景。 3轴加速度计&#xff08;Accelerometer&…

电子档案数据迁移什么意思?电子档案数据迁移流程

电子档案数据迁移是指将现有的电子档案数据从一个系统或存储设备迁移到另一个系统或存储设备的过程。这个过程可以包括将数据从旧的存储介质转移到新的存储介质&#xff0c;或将数据从一个系统迁移到另一个系统。电子档案数据迁移通常是为了更好地管理和保护档案数据&#xff0…

推荐一款搜索文件夹中内容的软件--FileSeek

介绍一个在文件夹中搜索文件内容的软件FileSeek 软件中一些功能较为清晰&#xff0c;不懂的话翻一下就行&#xff0c;我觉得使用其普通功能就可以解决大多数问题&#xff0c;就是在文件夹中查找文件中的内容。这帮助我们进行内容筛选有很大的帮助。例如上诉案例就是在ctf中我们…

【Flutter】三个Channel(Android-java / Ios-swift)

Channel 实现与原生通信 【1】MethodChannel flutter MethodChannel官方文档 通过MethodChannel来传递数据&#xff0c;调用方法 案例 分别调用Android和Ios原生的获取电量的方法 Flutter端 实例一个MethodChannel&#xff0c; 唯一标识name&#xff0c;定义方法名称get…

linux大文件IO

在Linux中处理大文件&#xff08;通常指大小超过2GB的文件&#xff09;时&#xff0c;需要使用特定的系统调用和标志&#xff0c;以确保程序能够正确地处理大文件的读写。这主要是因为在32位系统上&#xff0c;传统的文件偏移量和文件大小使用off_t类型表示&#xff0c;它通常是…

RabbitMQ的自动应答和手动应答,解决重试死循环

RabbitMQ的自动应答和手动应答&#xff0c;解决重试死循环 1.应答模式 RabbitMQ 中的消息应答模式主要包括两种&#xff1a;自动应答&#xff08;Automatic Acknowledgement&#xff09;和手动应答&#xff08;Manual Acknowledgement&#xff09;。 1、自动应答&#xff1a;…

ctfshow web入门 文件上传web162--web167

web162 session文件包含条件竞争 直接包含不传马了 我们上传的文件如果不符合要求&#xff0c;就会被删除&#xff0c;导致成功上传无法访问&#xff0c;没有用。但是如果我们上传的速度比服务器删的速度快&#xff0c;就可以了。 上传.user.ini GIF89a auto_append_file/tmp/…

医院预约系统微信小程序APP前后端

医院预约系统具体功能介绍&#xff1a;展示信息、可以注册和登录&#xff0c; 预约&#xff08;包含各个科室的预约&#xff0c;可以预约每个各个医生&#xff09;&#xff0c;就诊引导包含预约的具体信息&#xff0c;包含就诊时间、就诊科室、就诊医生以及就诊人信息、和支付状…

Unity之Unity面试题(三)

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之Unity面试题&#xff08;三&#xff09; TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取…

2025考研数学汤家凤基础班百度网盘视频+强化班PDF讲义持续更新

如果25考研想全程跟张宇老师&#xff0c;可以参考下面这个表格来使用资料&#xff1a; 2025考研数学全程课&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1e6wA4OiH_EJpZPXPxoHYwg 提取码&#xff1a;om45 考研数学 考研数学无非就是汤家凤老师&#xff0c;张宇老师…

政安晨:【深度学习神经网络基础】(五)—— 霍普菲尔德神经网络和玻尔兹曼机

目录 简述 霍普菲尔德神经网络 训练霍普菲尔德神经网络 Hopfield-Tank神经网络 玻尔兹曼机 总之 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&am…

Linux安装Oracle11g(无图形界面下的静默安装)

Oracle11g安装文档-Linux静默安装 环境准备安装数据库配置监听器创建数据库测试打开防火墙 环境准备 创建组和用户 [rootlocalhost ~]# groupadd oinstall #创建oinstall组 [rootlocalhost ~]# groupadd dba  #创建dba组 [rootlocalhost ~]# useradd -g oinstall -G dba -m…

【快捷部署】016_Ollama(CPU only版)

&#x1f4e3;【快捷部署系列】016期信息 编号选型版本操作系统部署形式部署模式复检时间016Ollama&#xff08;CPU only&#xff09;latestCentOS 7.XDocker单机2024-04-10 注意事项&#xff1a; 1、目前镜像及大模型下载速度尚可&#xff0c;但由于容量较大&#xff0c;所以…

K8S:常用资源对象操作

文章目录 一、使用Replication Controller(RC)、Replica Set(RS) 管理Pod1 Replication Controller&#xff08;RC&#xff09;2 Replication Set&#xff08;RS&#xff09; 二、Deployment的使用1 创建2 滚动升级3 回滚Deployment三、 Pod 自动扩缩容HPA1 使用kubectl autosc…

thinkphp5关联预载入with指定字段属性查询

一、thinkphp5.0 如果要指定属性查询&#xff0c;可以使用&#xff1a; $list User::field(id,name)->with([profile>function($query){$query->field(email,phone);}])->select([1,2,3]); foreach($list as $user){// 获取用户关联的profile模型数据dump($user…

典型新能源汽车热管理系统方案分析

目前行业具有代表性的热管理系统有PTC电加热方案、热泵方案&#xff08;特斯拉八通阀热泵、吉利直接式热泵&#xff09;、威马的柴油加热方案以及以理想为代表的插电式混动车方案。 小鹏P7整车热管理方案分析&#xff08;PTC电加热方案&#xff09; 小鹏P7作为小鹏汽车的第2款…

NzN的数据结构--插入排序

排序排序我要Disney&#xff0c;今天我们先来看看经典排序算法里的插入排序&#xff0c;先三连后看才是好习惯&#xff01;&#xff01;&#xff01; 目录 一、排序的概念及应用 1. 排序的概念 2. 排序的应用 3. 常见的排序算法 二、插入排序 1. 基本思想 2. 直接插入排…

pyside6的QSpinBox自定义特性初步研究(二)

当前的需求是&#xff0c;蓝色背景的画面&#xff0c;需要一个相对应色系的QSpinBox部件。已有的部件风格是这样的&#xff0c;需要新的部件与之般配。 首先新建一个QDoubleSpinBox&#xff0c;并定义其背景色和边框&#xff1a; QDoubleSpinBox { color: white; border:1px…

Vue3---基础1(认识,创建)

变化 相对于Vue2&#xff0c;Vue3的变化&#xff1a; 性能的提升 打包大小减少 41% 初次渲染快 55%&#xff0c;更新渲染快133% 内存减少54% 源码的升级 使用 proxy 代替 defineProperty 实现响应式 重写虚拟 DOM 的实现和 Tree-shaking TypeScript Vue3就可以更好的支持TypeSc…