Topological Sort
模板
首先通过Map创建图graph,graph的key是节点,graph的value是节点key后继的集合;一般如下定义
1
Map<Character, Set<Character>> graph = new HashMap<>();创建一个节点映射其入度的Map;一般如下定义
1
Map<Character, Integer> inDegrees = new HashMap<>();初始化graph的节点,把每个节点都加入图中;初始化inDegrees
1
2
3
4
5
6for (String word : words) {
for (char ch : word.toCharArray()) {
graph.putIfAbsent(ch, new HashSet<>());
inDegrees.putIfAbsent(ch, 0);
}
}初始化graph的边,同时计算入度
1
2
3
4
5
6
7
8
9
10
11
12
13for (int i = 1; i < words.length; ++i) {
String word1 = words[i - 1], word2 = words[i];
for (int j = 0; j < word1.length() && j < word2.length(); ++j) {
char ch1 = word1.charAt(j), ch2 = word2.charAt(j);
if (ch1 != ch2) {
if (!graph.get(ch1).contains(ch2)) {
graph.get(ch1).add(ch2);
inDegrees.put(ch2, inDegrees.get(ch2) + 1);
}
break;
}
}
}创建队列,并把入度为0的节点加入队列
1
2
3
4Queue<Character> queue = new LinkedList<>();
for (char key : inDegrees.keySet())
if (inDegrees.get(key) == 0)
queue.offer(key);创建一个记录结果的容器,每次从queue中取出一个节点,把该节点加入结果集,并将该节点后继的入度减一,如果该节点后继的入度为0,则加入队列
1
2
3
4
5
6
7
8
9
10StringBuilder sb = new StringBuilder();
while (!queue.isEmpty()) {
char node = queue.poll();
sb.append(node);
for (char next : graph.get(node)) {
inDegrees.put(next, inDegrees.get(next) - 1);
if (inDegrees.get(next) == 0)
queue.offer(next);
}
}如果结果集包含所有节点,则是有向无环图
207. 课程表
方法一:拓扑排序
1 | |
210. 课程表 II
方法一:拓扑排序
1 | |
剑指 Offer II 114. 外星文字典
方法一:拓扑排序
1 | |
剑指 Offer II 115. 重建序列
方法一:拓扑排序
判断有向图的拓扑排序序列是否唯一
1 | |
二刷
返回queue.isEmpty();就好,如下例,节点1和3的入度都为0,queue.size()为二,不进入while(queue.size() == 1),此时queue中有1和3,不为空,所以返回false
1 | |
代码
1 | |
三刷
inDegrees换成数组
1 | |

方法一:拓扑排序
此题的思路是:找到所有边缘上的节点,然后一层一层删除,直到队列为空,那队列中最后的值就是答案了。比如样例1:边缘的节点为0,2,3,删除后就只剩下1了。不难发现,边缘的节点就是度数为1的节点。
定义graph时为空,需要初始化每一个List
1
List<Integer>[] graph = new List[n];
1 | |
二刷
1 | |
802. 找到最终的安全状态

方法一:拓扑排序
- 找到所有不进入环的节点
- 求反向图,拓扑排序
- 入度为0的节点符合要求
1 | |
二刷
1 | |
2603. 收集树中金币

方法一:两次拓扑排序
1 | |
2876. 有向图访问计数

方法一:拓扑排序 + 反向图
注意内向基环图可以包含多个环!!!
1 | |
2360. 图中的最长环

方法一:拓扑排序 + 基环树
1 | |
Topological Sort
https://leopol1d.github.io/2023/05/29/topological-sort/