我们从题目中可以看出来:
思路如下:
int n = graph.length;
// 初始化邻接图和出度数组
List<Integer>[] adj = new ArrayList[n];
int[] outDegree = new int[n];
for (int i = 0; i < n; i++) {
adj[i] = new ArrayList<>();
}
// 构建邻接图和出度数组,这里的索引就是一条有向边的起点。
for (int i = 0; i < n; i++) {
// 出度的个数,就是二维的长度
outDegree[i] = graph[i].length;
// 反向构建邻接图
for (int j = 0; j < graph[i].length; j++) {
adj[graph[i][j]].add(i);
}
}
// 将出度为0的入队
LinkedList<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (outDegree[i] == 0) {
queue.offer(i);
}
}
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Integer cur = queue.poll();
// adj[cur] 就是 pre --> 终端节点,拿到的所有 pre
for (Integer pre : adj[cur]) {
// 出度 -1,若为0,继续入队
if (--outDegree[pre] == 0) {
queue.offer(pre);
}
}
}
}
public class Test802 {
public List<Integer> eventualSafeNodes(int[][] graph) {
int n = graph.length;
// 初始化邻接图和出度数组
List<Integer>[] adj = new ArrayList[n];
int[] outDegree = new int[n];
for (int i = 0; i < n; i++) {
adj[i] = new ArrayList<>();
}
// 构建邻接图和出度数组,这里的索引就是一条有向边的起点。
for (int i = 0; i < n; i++) {
// 出度的个数,就是二维的长度
outDegree[i] = graph[i].length;
// 反向构建邻接图
for (int j = 0; j < graph[i].length; j++) {
adj[graph[i][j]].add(i);
}
}
// 将出度为0的入队
LinkedList<Integer> queue = new LinkedList<>();
for (int i = 0; i < n; i++) {
if (outDegree[i] == 0) {
queue.offer(i);
}
}
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Integer cur = queue.poll();
// adj[cur] 就是 pre --> 终端节点,拿到的所有 pre
for (Integer pre : adj[cur]) {
// 出度 -1,若为0,继续入队
if (--outDegree[pre] == 0) {
queue.offer(pre);
}
}
}
}
// 最终出度为0的全部加入到结果集中
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < n; i++) {
if (outDegree[i] == 0) {
res.add(i);
}
}
return res;
}
}