刷题训练之 BFS 解决拓扑排序
> 作者:დ旧言~
> 座右铭:松树千年终是朽,槿花一日自为荣。> 目标:熟练掌握 BFS 解决拓扑排序算法。
> 毒鸡汤:学习,学习,再学习 ! 学,然后知不足。
> 专栏选自:刷题训练营
> 望小伙伴们点赞👍收藏✨加关注哟💕💕
🌟前言分析
最早博主续写了牛客网130道题,这块的刷题是让同学们快速进入C语言,而我们学习c++已经有一段时间了,知识储备已经足够了但缺少了实战,面对这块短板博主续写刷题训练,针对性学习,把相似的题目归类,系统的刷题,而我们刷题的官网可以参考:
⭐知识讲解
基本思想:
🌙topic-->1
题目链接:1. - 力扣(LeetCode)
题目分析:
你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses - 1 。
在选修某些课程之前需要一些先修课程。 先修课程按数组 prerequisites 给出,其中 prerequisites[i] = [ai, bi] ,表示如果要学习课程 ai 则 必须 先学习课程 bi 。
算法原理:
- 解法:BFS 拓扑排序
图解:
代码演示:
class Solution {
public:
bool canFinish(int n, vector<vector<int>>& p) {
unordered_map<int, vector<int>> edges; // 邻接表
vector<int> in(n); // 存储每⼀个结点的⼊度
// 1. 建图
for (auto& e : p) {
int a = e[0], b = e[1];
edges[b].push_back(a);
in[a]++;
}
// 2. 拓扑排序 - bfs
queue<int> q;
// 把所有⼊度为 0 的点加⼊到队列中
for (int i = 0; i < n; i++) {
if (in[i] == 0)
q.push(i);
}
// 层序遍历
while (!q.empty()) {
int t = q.front();
q.pop();
// 修改相连的边
for (int e : edges[t]) {
in[e]--;
if (in[e] == 0)
q.push(e);
}
}
// 3. 判断是否有环
for (int i : in)
if (i)
return false;
return true;
}
};
🌙topic-->2
题目链接:2. - 力扣(LeetCode)
题目分析:
现在你总共有 numCourses 门课需要选,记为 0 到 numCourses - 1。给你一个数组 prerequisites ,其中 prerequisites[i] = [ai, bi] ,表示在选修课程 ai 前 必须 先选修 bi 。
算法原理:
- 解法:BFS 拓扑排序
图解:本质和上面的题型一样,这里就不再赘述了。
代码演示:
class Solution {
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
// 1. 准备⼯作
vector<vector<int>> edges(numCourses); // 邻接表存储图
vector<int> in(numCourses); // 存储每⼀个点的⼊度
// 2. 建图
for (auto& p : prerequisites) {
int a = p[0], b = p[1]; // b -> a
edges[b].push_back(a);
in[a]++;
}
// 3. 拓扑排序
vector<int> ret; // 统计排序后的结果
queue<int> q;
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 a : edges[t]) {
in[a]--;
if (in[a] == 0)
q.push(a);
}
}
if (ret.size() == numCourses)
return ret;
else
return {};
}
};
🌙topic-->3
题目链接:3. - 力扣(LeetCode)
题目分析:
现有一种使用英语字母的外星文语言,这门语言的字母顺序与英语顺序不同。
给定一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。
请你根据该词典还原出此语言中已知的字母顺序,并 按字母递增顺序 排列。若不存在合法字母顺序,返回 "" 。若存在多种可能的合法字母顺序,返回其中 任意一种 顺序即可。
算法原理:
- 解法:BFS 拓扑排序
图解:
代码演示:
class Solution {
unordered_map<char, unordered_set<char>> edges; // 邻接表来存储图
unordered_map<char, int> in; // 统计⼊度
bool cheak; // 处理边界情况
public:
string alienOrder(vector<string>& words) {
// 1. 建图 + 初始化⼊度哈希表
for (auto& s : words) {
for (auto ch : s) {
in[ch] = 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 (cheak)
return "";
}
}
// 2. 拓扑排序
queue<char> q;
for (auto& [a, b] : in) {
if (b == 0)
q.push(a);
}
string ret;
while (q.size()) {
char t = q.front();
q.pop();
ret += t;
for (char ch : edges[t]) {
if (--in[ch] == 0)
q.push(ch);
}
}
// 3. 判断
for (auto& [a, b] : in)
if (b != 0)
return "";
return ret;
}
void add(string& s1, string& s2) {
int n = min(s1.size(), s2.size());
int i = 0;
for (; i < n; i++) {
if (s1[i] != s2[i]) {
char a = s1[i], b = s2[i]; // a -> b
if (!edges.count(a) || !edges[a].count(b)) {
edges[a].insert(b);
in[b]++;
}
break;
}
}
if (i == s2.size() && i < s1.size())
cheak = true;
}
};
🌟结束语
今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。
更多推荐









所有评论(0)