有华为OD考试扣扣交流群可加:948025485
可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳od1336
了解算法冲刺训练
一个应用启动时,会有多个初始化任务需要执行,并且任务之间有依赖关系,例如A
任务依赖B
任务,那么必须在B
任务执行完成之后,才能开始执行A
任务。
现在给出多条任务依赖关系的规则,请输入任务的顺序执行序列,规则采用贪婪策略,即一个任务如果没有依赖的任务,则立刻开始执行,如果同时有多个任务要执行,则根据任务名称字母顺序排序。
例如:B
任务依赖A
任务,C
任务依赖A
任务,D
任务依赖B
任务和C
任务,同时,D
任务还依赖E
任务。那么执行任务的顺序由先到后是:A
任务,E
任务,B
任务,C
任务,D
任务。这里A
和E
任务都是没有依赖的,立即执行
输入参数每个元素都表示任意两个任务之间的依赖关系,输入参数中符号->
表示依赖方向,例A->B
表示A
依赖B
,多个依赖之间用单个空格分割
输出为排序后的启动任务列表,多个任务之间用单个空格分割
A->B C->B
B A C
任务A
和C
都依赖于任务B
。任务B
执行后,A
和C
立即执行,A
和C
的执行顺序按照字典序排列。
B->A C->A D->B D->C D->E
A E B C D
看到存在依赖关系,立马想到拓扑排序。
本题一个小难点在于如何对同级节点进行排序。
在BFS每一层搜索之前,可以构建一个空数组nodes_new
,来储存搜索过程中新出现的入度为0
的节点。这些新出现的这些节点属于拓扑排序中的同级节点,需要在for
循环结束后进行排序,然后加入到ans
中。
代码如下
while q:
nodes_new = list()
qSize = len(q)
for _ in range(qSize):
cur_node = q.popleft()
for nxt_node in neighbor_dic[cur_node]:
indegree_dic[nxt_node] -= 1
if indegree_dic[nxt_node] == 0:
nodes_new.append(nxt_node)
q.append(nxt_node)
nodes_new.sort()
ans += nodes_new
# 题目:【BFS】2023C-启动多任务排序
# 分值:200
# 作者:闭着眼睛学数理化
# 算法:BFS/拓扑排序
# 代码看不懂的地方,请直接在群上提问
from collections import deque, defaultdict
# 对输入进行分割,得到若干个字符串,每一个字符串包含依赖关系
lst = input().split()
# 构建邻接表
neighbor_dic = defaultdict(list)
# 构建入度哈希表(因为节点名字是字符串而不是数字,因此用哈希表而不是数组)
indegree_dic = defaultdict(int)
# 遍历lst中的每一对依赖关系
for pairs in lst:
# 根据"->"进行分割,得到节点a和b
# "a->b"表示节点a依赖于节点b
# 必须执行节点b之后,才能执行节点a
a, b = pairs.split("->")
# a为b的邻居,延长b的邻接节点
neighbor_dic[b].append(a)
# 节点a的入度增加
indegree_dic[a] += 1
# 初始化答案数组,其中入度为0的节点为初始节点,同时根据字典序进行排序
ans = sorted(k for k in neighbor_dic.keys() if indegree_dic[k] == 0)
# 初始化队列,其中队中元素为ans中的元素
q = deque(ans)
# BFS
while q:
# 初始化一个列表,储存新出现的入度为0的节点
# 新出现的这些节点,需要在for循环结束后立即执行,加入到ans中
nodes_new = list()
# 获得当前层的节点数
qSize = len(q)
# 循环qSize次,弹出队列中所有节点
for _ in range(qSize):
# 弹出当前队头节点cur_node
cur_node = q.popleft()
# 考虑cur_node的所有近邻节点nxt_node
for nxt_node in neighbor_dic[cur_node]:
# 近邻nxt_node的入度-1
indegree_dic[nxt_node] -= 1
# 如果该近邻节点的入度降为0
if indegree_dic[nxt_node] == 0:
# 将其加入nodes_new数组中
nodes_new.append(nxt_node)
# 将其加入q中
q.append(nxt_node)
# 对nodes_new根据字典序进行排序,然后加在ans后面
# 表示需要立即执行nodes_new中的节点
nodes_new.sort()
ans += nodes_new
print(*ans)
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
String[] lst = input.split(" ");
Map<String, List<String>> neighborDic = new HashMap<>();
Map<String, Integer> indegreeDic = new HashMap<>();
for (String pairs : lst) {
int pos = pairs.indexOf("->");
String a = pairs.substring(0, pos);
String b = pairs.substring(pos + 2);
neighborDic.computeIfAbsent(b, k -> new ArrayList<>()).add(a);
indegreeDic.put(a, indegreeDic.getOrDefault(a, 0) + 1);
}
List<String> ans = new ArrayList<>();
for (String node : neighborDic.keySet()) {
if (!indegreeDic.containsKey(node)) {
ans.add(node);
}
}
Collections.sort(ans);
Queue<String> q = new LinkedList<>(ans);
while (!q.isEmpty()) {
List<String> nodesNew = new ArrayList<>();
int qSize = q.size();
for (int i = 0; i < qSize; i++) {
String curNode = q.poll();
if (neighborDic.containsKey(curNode)) {
for (String nxtNode : neighborDic.get(curNode)) {
indegreeDic.put(nxtNode, indegreeDic.get(nxtNode) - 1);
if (indegreeDic.get(nxtNode) == 0) {
nodesNew.add(nxtNode);
q.add(nxtNode);
}
}
}
}
Collections.sort(nodesNew);
ans.addAll(nodesNew);
}
for (String node : ans) {
System.out.print(node + " ");
}
}
}
#include
#include
#include
#include
#include
using namespace std;
int main() {
string input;
getline(cin, input);
vector<string> lst;
string temp;
for (char i : input) {
if (i == ' ') {
lst.push_back(temp);
temp = "";
} else {
temp += i;
}
}
lst.push_back(temp);
unordered_map<string, vector<string>> neighborDic;
unordered_map<string, int> indegreeDic;
for (string pairs : lst) {
string delimiter = "->";
size_t pos = pairs.find(delimiter);
string a = pairs.substr(0, pos);
string b = pairs.substr(pos + delimiter.length());
neighborDic[b].push_back(a);
indegreeDic[a]++;
}
vector<string> ans;
for (auto node : neighborDic) {
if (indegreeDic.find(node.first) == indegreeDic.end()) {
ans.push_back(node.first);
}
}
sort(ans.begin(), ans.end());
queue<string> q;
for (string node : ans) {
q.push(node);
}
while (!q.empty()) {
vector<string> nodesNew;
int qSize = q.size();
for (int i = 0; i < qSize; i++) {
string curNode = q.front();
q.pop();
if (neighborDic.find(curNode) != neighborDic.end()) {
for (string nxtNode : neighborDic[curNode]) {
indegreeDic[nxtNode]--;
if (indegreeDic[nxtNode] == 0) {
nodesNew.push_back(nxtNode);
q.push(nxtNode);
}
}
}
}
sort(nodesNew.begin(), nodesNew.end());
ans.insert(ans.end(), nodesNew.begin(), nodesNew.end());
}
for (string node : ans) {
cout << node << " ";
}
return 0;
}
时间复杂度:O(N)
。
空间复杂度:O(N)
。
华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!
课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!
60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
可查看链接 大厂真题汇总 & OD真题汇总(持续更新)
绿色聊天软件戳 od1336
了解更多