In a directed graph, we start at some node and every turn, walk along a directed edge of the graph. If we reach a node that is terminal (that is, it has no outgoing directed edges), we stop.
Now, say our starting node is eventually safe if and only if we must eventually walk to a terminal node. More specifically, there exists a natural number K
so that for any choice of where to walk, we must have stopped at a terminal node in less than K
steps.
Which nodes are eventually safe? Return them as an array in sorted order.
The directed graph has N
nodes with labels 0, 1, ..., N-1
, where N
is the length of graph
. The graph is given in the following form: graph[i]
is a list of labels j
such that (i, j)
is a directed edge of the graph.
Example:
Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output: [2,4,5,6]
Here is a diagram of the above graph.
思路:从每个点开始做dfs,只有每条路都是通往safe的点,那么这个点就是safe的,只要有一条是有cycle的,这题巧妙的地方是不仅仅是看是否有环,而是看状态,如果有环有时候不行,有时候是可以的;所以这题不能用hashset来detect是否有环,得用状态来表示;
1
/ \
2 -> 3 -> 4
上面的图2,3,4是safe的,实际上1也是safe的,因为1的neighbor虽然visite过了,但是neighbor都是safe的;
class Solution {
public List<Integer> eventualSafeNodes(int[][] graph) {
List<Integer> list = new ArrayList<Integer>();
// 0, unvisited;
// 1, safe;
// 2, unsafe;
int n = graph.length;
int[] status = new int[n];
for(int i = 0; i < n; i++) {
if(dfs(graph, i, status)) {
list.add(i);
}
}
return list;
}
private boolean dfs(int[][] graph, int node, int[] status) {
if(status[node] != 0) { // 这里用状态来表示,有可能之前visite过了,但是是safe的;
return status[node] == 1;
}
status[node] = 2; // 每次默认是unsafe;
for(Integer neighbor: graph[node]) {
if(!dfs(graph, neighbor, status)) {
return false;
}
}
status[node] = 1; // 经过检测之后,neighbor都是safe,那么才赋值safe;
return true;
}
}