模板题目链接
Leetcode 210 Course Schedule II
Leetcode 2115 Find all possible Reciptes from given supplies
拓扑排序是在有向无环图中以图中节点依赖关系对节点进行排序。例如求解前置课程,求解程序中调用包的依赖关系等等。
拓扑排序思路
拓扑排序思路与BFS搜索类似,只不过在搜索前需要进行建图以及每个节点的入度计算。
1. 入度:每一个节点的入度可以理解为指向这个节点的节点个数
2. 有向图:如果节点之间链接较为稀疏通常使用邻接表HashMap<Node, List<Node>>形式来存储节点关系
有向图邻接表和入度计算完成后,即可使用类似BFS方法进行遍历,创建一个队列进行存储,如果有节点入度为0那么就将该节点加入队列,然后找出与该节点相邻节点并将他们的入度-1,如果有新的入度为0的点出现继续加入队列直到为空为止。
注:如果是有环形结构,那么你在拓扑排序可能会出现死循环,因为环形结构两个节点会不断进入队列。但也可以解决,可以设置一个阈值,如果加入队列节点个数超过了图中节点个数说明环形存在,即刻跳出。
代码如下:()
//建图
HashMap<String, List<String>> graph = new HashMap<>();
//入度
HashMap<String, Integer> indegree = new HashMap<>();
HashSet<String> have = new HashSet<>();
// 计算入度和邻接表
for(int i=0; i<ingredients.size(); i++) {
String r = recipes[i];
have.add(r);
indegree.put(r, indegree.getOrDefault(r, 0));
for (String ing: ingredients.get(i)) {
graph.putIfAbsent(ing, new ArrayList<>());
graph.get(ing).add(r);
indegree.put(r, indegree.get(r)+1);
}
}
// BFS 搜索
Queue<String> q = new LinkedList<>();
for (String sup: supplies) {
q.offer(sup);
}
while(!q.isEmpty()){
String curr = q.poll();
if (!graph.containsKey(curr)) continue;
for (String nei: graph.get(curr)) {
// 入度-1
indegree.put(nei, indegree.get(nei)-1);
if (indegree.get(nei)==0) q.offer(nei);
}
}
时间复杂度:,遍历所有节点;空间复杂度:,保存所有节点以及入度。