当前位置: 首页 > news >正文

BFS算法篇——打开智慧之门,BFS算法在拓扑排序中的诗意探索(下)

文章目录

  • 引言
  • 一、课程表
    • 1.1 题目链接:https://leetcode.cn/problems/course-schedule/description/
    • 1.2 题目分析:
    • 1.3 思路讲解:
    • 1.4 代码实现:
  • 二、课程表||
    • 2.1 题目链接:https://leetcode.cn/problems/course-schedule-ii/description/
    • 2.2 题目分析:
    • 2.3 思路讲解:
    • 2.4 代码实现:
  • 三、火星词典
    • 3.1 题目链接:https://leetcode.cn/problems/Jf1JuT/description/
    • 3.2 题目分析:
    • 3.3 思路讲解:
    • 3.4 代码实现:
  • 小结

在这里插入图片描述

引言

上篇我们介绍了BFS解决拓扑排序的背景知识,本篇我们将结合具体题目分析,进一步深化对于该算法的理解运用。

一、课程表

1.1 题目链接:https://leetcode.cn/problems/course-schedule/description/

1.2 题目分析:

  • numCourses 表示要学的课程的数量
  • prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
  • 如果存在能按照顺序学完的可能,返回true,否则返回false

1.3 思路讲解:

该题为一个明显的拓扑排序问题,根据上篇讲解,我们可以这样子处理

  • 首先构建邻接表,先决条件pre表示的顺序即为b->a,作为边加入其中
  • 同时,由于学习a之前必须要学习b,因此a的入度加1
  • 之后将入度为0的节点入队列,层序遍历即可

1.4 代码实现:

class Solution {
public:bool canFinish(int n, vector<vector<int>>& prerequisites) {unordered_map<int,vector<int>> edges;//邻接表vector<int> in(n);//入度//建图for(auto e: prerequisites){int a=e[0],b=e[1];edges[b].push_back(a);in[a]++;}queue<int> q;//将入度为0的节点入队列for(int i=0;i<n;i++){if(in[i]==0){q.push(i);}}//层序遍历while(q.size()){int t=q.front();q.pop();for(int e : edges[t]){in[e]--;if(in[e]==0){q.push(e);}}}for(int i=0;i<n;i++){if(in[i]){return false;}//说明无法学完所有课程}return true;}
};

二、课程表||

2.1 题目链接:https://leetcode.cn/problems/course-schedule-ii/description/

2.2 题目分析:

该题与上题要求基本相同,只是返回值要求返回可能的一种学习顺序,如果不存在,则返回空数组

2.3 思路讲解:

判断是否可以学习的思路与上题相同,我们只需要在层序遍历时,用一个数组记录当前学习顺序即可。

2.4 代码实现:

class Solution {
public:vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {unordered_map<int,vector<int>> edges;//邻接表vector<int> in(numCourses);//入度vector<int> ret;//返回值vector<int> temp;//空数组queue<int> q;//建图for(auto e:prerequisites){int a=e[0],b=e[1];edges[b].push_back(a);in[a]++;}//入度为0的节点入队列for(int i=0;i<numCourses;i++){if(in[i]==0){q.push(i);}}while(q.size()){int t=q.front();q.pop();ret.push_back(t);//更新结果for(int e:edges[t]){in[e]--;if(in[e]==0){q.push(e);}}}for(int i=0;i<numCourses;i++){if(in[i]){return temp;}}//存在未完成情况,返回空数组return ret;}
};

三、火星词典

3.1 题目链接:https://leetcode.cn/problems/Jf1JuT/description/

3.2 题目分析:

题目要求一时间难以读懂,我们来简单翻译一下:

  • 给定的word里面已经按一种新的字母顺序排列好

假设 words = [“wrt”,“wrf”,“er”,“ett”,“rftt”],我们可以得到字母之间的一些依赖关系:

  • 比如从 “wrt” 和 “wrf” 可以得出 t 在 f 之前(因为 “t” 是两个单词中的不同字母,且在相同位置上不同)。

  • 从 “er” 和 “ett” 中可以得出 r 在 e 之前。

最终需要返回题目中外星词典的递增顺序,若不存在合法的顺序,则返回空

3.3 思路讲解:

我们通过比较相邻的单词,找出它们的第一个不同字母。这些字母的顺序关系就可以帮助我们构建字母的顺序图。

图的构建:

  • 我们可以通过图来表示字母之间的顺序关系。每个字母是图中的一个节点,而字母之间的顺序关系是边。

拓扑排序:

  • 通过拓扑排序的方法,我们可以得到字母的正确排序。如果有环,则说明字母顺序无法确定,返回空字符串。

3.4 代码实现:

class Solution {
public:unordered_map<char,unordered_set<char>> edges;//边unordered_map<char,int> in;//入度bool check;//处理特殊情况void add(string& s1,string& s2){int n=min(s1.size(),s2.size());int i;for( i=0;i<n;i++){if(s1[i]!=s2[i]){char a=s1[i],b=s2[i];if(!edges.count(a) || !edges[a].count(b))//如果之前为记录过,则记录这条边a->b{edges[a].insert(b);in[b]++;//更新边和入度节点}break;//注意跳出循环}}if(i==s2.size()&&i<s1.size())//处理abc ab这种特殊情况{check=true;}}string alienOrder(vector<string>& words) {//建图和初始化for(auto e: words){for(auto ch:e){in[ch]=0;}//将所有字符的入度都初始化为0}int n=words.size();for(int i=0;i<n;i++){for(int j=i+1;j<n;j++){add(words[i],words[j]);if(check){return "";//存在非法情况}}}//拓扑排序queue<char> q;string ret;//将所有入度为0的节点for(auto [a,b] :in){if(b==0){q.push(a);}}while(q.size()){char t=q.front();q.pop();ret+=t;for(auto e:edges[t]){if(--in[e]==0) q.push(e);}}for(auto [a,b] :in){if(b!=0){return "";}}//判断是否存在不合法顺序return ret;}
};

小结

本篇关于BFS解决拓扑排序的讲解就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持斧正!!!

在这里插入图片描述

http://www.xdnf.cn/news/428743.html

相关文章:

  • 12V转3.3V3A同步降压转换芯片WT6030
  • nginx配置反向代理支持CORS跨域请求
  • 【手表维修专用软件】佳易王手表钟表保养维护服务跟踪管理系统:保养维护登记,维修进度跟踪!#手表维修管理系统教程 #铭表设备维修记录软件#操作简单软件下载
  • 电子元器件结温计算与降额设计
  • Python训练营打卡——DAY24(2025.5.13)
  • aardio - 将文本生成CSS格式显示
  • 移动端(手机)ECharts 的myChart.on(‘click‘,还生效吗我怎么触发不了,没得鼠标触发不了点击事件
  • 物联网设备状态监控全解析:从告警参数到静默管理的深度指南-优雅草卓伊凡
  • 传输层:UDP协议
  • 网络安全-等级保护(等保) 2-3 GB/T 22240—2020《信息安全技术 网络安全等级保护定级指南》-2020-04-28发布【现行】
  • 从HTTP轮询到WebSocket:如何让体育API性能提升100倍?
  • Postgresql与openguass对比
  • hab机制
  • 【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)
  • [Java][Leetcode middle] 55. 跳跃游戏
  • 线程的概念和控制
  • [SAP] 通过事务码Tcode获取程序名
  • Nacos源码—9.Nacos升级gRPC分析七
  • Leetcode (力扣)做题记录 hot100(49,136,169,20)
  • YOLOv1:开启实时目标检测的新篇章
  • SWMM的快速建模方法、SWMM与其他软件之间的数据转换:排水防涝、海绵城市设计等技术与二次开发
  • dockerdesktop 重新安装
  • SQL Server中delete table和truncate table删除全表数据哪个快?
  • 云手机服务器搭建
  • TCP协议中的IP地址/域名
  • 在scala中sparkSQL连接mysql并添加新数据
  • 单链表:多米诺骨牌的奇妙旅程
  • Shinkai开源程序 是一个双击安装 AI 管理器(本地和远程),它允许您使用简单的 UI 在 5 分钟或更短的时间内创建 AI 代理
  • 量化感知训练与 PyTorch 的哪些事
  • 力扣-226.翻转二叉树