802. Find Eventual Safe States
https://leetcode.com/problems/find-eventual-safe-states
Problem
Intuition
- Nhận định: node A là safe node khi 1 trong 2 điều kiện sau xảy ra:
- node A là terminal node (không có edge nào xuất phát từ node đó - outdegree = 0)
- “tất cả” các node khác xuất phát từ node A đều là safe node
Approach
- Dùng DFS để tìm các safe node, và dùng
color
array để đánh dấu từng node:- NONE: chưa duyệt qua node này
- VISITING: đang duyệt node này, tránh trường hợp cyclic (node A –> node B –> … -> node A)
- NOT_SAFE: not safe node
- SAFE: safe node
- Để ý, mảng
color
được dùng xuất phát từ ý tưởngtopo
sort
Implementation
class Solution {
private static final int NONE = 0;
private static final int VISITING = 1;
private static final int NOT_SAFE = 3;
private static final int SAFE = 4;
private int[][] graph;
private int n;
private List<Integer> ans;
private int[] color;
public List<Integer> eventualSafeNodes(int[][] graph) {
this.n = graph.length;
this.graph = graph;
this.ans = new ArrayList<>();
this.color = new int[n];
for (int i = 0; i < n; i++) {
if (color[i] != NONE) continue;
dfs(i);
}
Collections.sort(ans);
return ans;
}
private int dfs(int i) {
if (color[i] != NONE) {
return color[i];
}
// avoid cyclic
color[i] = VISITING;
// if node is terminal node
int outDeg = graph[i].length;
boolean isTerminalNode = outDeg == 0;
if (isTerminalNode) {
ans.add(i);
color[i] = SAFE;
return SAFE;
}
// node is safe node if all neighbors are safe node (or terminal node)
boolean isSafeNode = true;
for (int neighbor : graph[i]) {
int res = color[neighbor] == NONE ? dfs(neighbor) : color[neighbor];
if (res != SAFE) isSafeNode = false;
}
if (isSafeNode) {
ans.add(i);
color[i] = SAFE;
return SAFE;
} else {
color[i] = NOT_SAFE;
return NOT_SAFE;
}
}
}