简介: 拓扑排序问题中我们经常需要判断一个有向无环图是否有环或者能否按顺序走完等。
如何解答:
我们判断入度,通俗解释就是当前节点被指向的次数,
如果一个节点被指向的次数是0, 那么这个节点就是起始节点。
所有起始节点放入队列,循环遍历下一个或者多个节点
下一个节点次数减1并判断是否为0, 为0则放入队列
最后判断是否有节点没有走到
JAVA模板
存储入度(节点被指向次数),可以用Map或者数组来存放
Map<Integer, Integer> map = new HashMap<>(); //根据不同题目可以用int[]等
int[] degree = new int[numCourses];
构建图:
Map<Integer, List<Integer>> graph = new HashMap<>();
List[] edges = new ArrayList[numCourses];
for (int i = 0; i < numCourses; i++) {
edges[i] = new ArrayList<Integer>();
}
初始化图:用数组作为输入表示方向
for (int i = 0; i < prerequisites.length; i++) {
// 不同题目有from, to来表示指向
int from = prerequisites[i][1];
int to = prerequisites[i][0];
// 创建图,放入下一个节点到动态数组里
List<Integer> list = graph.getOrDefault(from, new ArrayList<Integer>());
list.add(to);
graph.put(from, list);
// 记录入度
map.put(to, map.getOrDefault(to, 0) + 1);
}
初始化队列:
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < numCourses; i++) {
if (!map.containsKey(i)) { //如果用数组则判断int[i]是否为0
queue.add(i);
}
}
队列中入度为0度节点排除和添加:
while (queue.size() != 0) {
int cur = queue.poll(); //当前入度为0度节点
if (graph.containsKey(cur)) {
for (Integer neighbor : graph.get(cur)) {
// 虚幻遍历当前节点的下一节点
map.put(neighbor, map.get(neighbor) - 1);
// 下一节点入度减1并判断是否为0(添加新的起始点)
if (!map.containsKey(neighbor) || map.get(neighbor) == 0) {
queue.add(neighbor);
}
}
}
}