一、题目
一个应用启动时,会有多个初始化任务需要执行,并且任务之间有依赖关系,例如A任务依赖B任务,那么必须在B任务执行完成之后,才能开始执行A任务。
现在给出多条任务依赖关系的规则,请输入任务的顺序执行序列,规则采用贪婪策略,即一个任务如果没有依赖的任务,则立刻开始执行,如果同时有多个任务要执行,则根据任务名称字母顺序排序。
例如:B任务依赖A任务,C任务依赖A任务,D任务依赖B任务和C任务,同时,D任务还依赖E任务。那么执行任务的顺序由先到后是:
A任务,E任务,B任务,C任务,D任务
这里A和E任务都是没有依赖的,立即执行。
二、输入
输入参数每个元素都表示任意两个任务之间的依赖关系,输入参数中符号"->"表示依赖方向,例如:
A->B:表示A依赖B
多个依赖之间用单个空格分隔
三、输出
输出排序后的启动任务列表,多个任务之间用单个空格分隔
四、示例
输入:
B->A C->A D->B D->C D->E
输出:
A E B C D
五、题解
- 这个是一个有向图的拓扑排序问题
- 注意输入中B->A表示 B 依赖 A,不同题目这里依赖关系表示会有区别
- 拓扑排序关键点是邻接表和入度表来分别表示依赖关系
5.1 Java 实现
package org.stone.study.algo.ex202411;
import java.util.*;
import java.util.stream.Collectors;
public class DependencySort {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String dependency = scanner.nextLine();
String res = sortByDependency(dependency);
System.out.println(res);
}
private static String sortByDependency(String dependencyStr) {
String[] arr = dependencyStr.split(" ");
Map<Character, List<Character>> dependencyMap = new HashMap<>();
Map<Character, Integer> inDegree = new HashMap<>();
Set<Character> taskSet = new HashSet<>();
for (String dep : arr) {
String[] depArr = dep.split("->");
char dependent = depArr[0].charAt(0);
char dependency = depArr[1].charAt(0);
dependencyMap.putIfAbsent(dependency, new ArrayList<>());
dependencyMap.get(dependency).add(dependent);
inDegree.put(dependent, inDegree.getOrDefault(dependent, 0) + 1);
if(!inDegree.containsKey(dependency)) {
inDegree.put(dependency, 0);
}
taskSet.add(dependent);
taskSet.add(dependency);
}
Queue<Character> queue = new LinkedList<>();
for (char task : inDegree.keySet()) {
if (inDegree.get(task) == 0) {
queue.offer(task);
}
}
List<Character> ans = new ArrayList<>();
while (!queue.isEmpty()) {
Character cur = queue.poll();
ans.add(cur);
for (Character dependent : dependencyMap.getOrDefault(cur, Collections.emptyList())) {
inDegree.put(dependent, inDegree.get(dependent) - 1);
if (inDegree.get(dependent) == 0) {
queue.offer(dependent);
}
}
}
if(ans.size() == taskSet.size()) {
return ans.stream().map(String::valueOf).collect(Collectors.joining(" "));
} else {
return "ERROR";
}
}
}
5.2 Python实现
from collections import deque
from collections import defaultdict
def sort_by_dependencies(dependencies):
graph = defaultdict(list)
in_degree = defaultdict(int)
tasks = set()
for dep in dependencies.split():
dependent, dependency = dep.split('->')
graph[dependency].append(dependent)
in_degree[dependent] += 1
tasks.update([dependent, dependency])
if dependency not in in_degree:
in_degree[dependency] = 0
queue = deque(sorted([task for task in tasks if in_degree[task] == 0]))
result = []
while queue:
cur = queue.popleft()
result.append(cur)
for neighbor in graph[cur]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
if len(result) != len(tasks):
return "ERROR"
return ' '.join(result)
if __name__ == '__main__':
dependencies = input()
ordered_dependencies = sort_by_dependencies(dependencies)
print(ordered_dependencies)