拓扑排序
三个数据存储的内容:
infosMap: 还没安排的课(以及该门课的上下游依赖关系)
inEdge: 还没上的上游课程的数量
inEdge==0表示这门课不依赖其他课,或者依赖的课已经上过了(i.e. 加入ans了)
neis: 下游的课号
queue: 安排了将要上的课。
ans: 已经上过的课。
1. 整理input, 建立infosMap:
2. 遍历infos, 将inEdge==0的课加入queue。
i.e. 该课不依赖其他课,直接安排上。
3. 逐一上掉安排了的课
假设上掉的课是x, x.neis = [y,z], 那么y,z的inEdge减1
如果y,z此时inEdge也等于0了,表示y,z也可以安排了,enqueue.
import java.util.*;
// topological sort
public class Solution {
class Info {
int nodeId;
int inEdge = 0;
final List<Integer> neis = new ArrayList<>();
Info(int id) {
nodeId = id;
}
}
public int[] findOrder (int[][] prerequisites, int n) {
Map<Integer, Info> infos = new HashMap<>();
for (int i = 0; i < n; i++)
infos.put(i, new Info(i));
for (int[] pre : prerequisites) {
int from = pre[1], to = pre[0];
infos.get(from).neis.add(to);
infos.get(to).inEdge++;
}
Queue<Info> q = new LinkedList<>();
Iterator<Map.Entry<Integer, Info>> it = infos.entrySet().iterator();
while(it.hasNext()) {
Map.Entry<Integer, Info> entry = it.next();
Info info = entry.getValue();
if (info.inEdge == 0) {
q.offer(info); // enqueue roots
it.remove(); // remove 0 inEdge node
}
}
List<Integer> ans = new ArrayList<>();
while (!q.isEmpty()) {
Info cur = q.poll();
ans.add(cur.nodeId);
for (int nei : cur.neis) {
Info neiInfo = infos.get(nei);
if (neiInfo == null) continue;
if (--neiInfo.inEdge == 0) {
infos.remove(neiInfo.nodeId);
q.offer(neiInfo); // remove 0 inEdge node
}
}
}
return ans.stream().mapToInt(x->x).toArray();
}
}