Problem Description
Given a directed graph where each node is labeled from 0 to n - 1 and represented as an array of neighbors, a terminal node is one with no outgoing edges and a safe node is one where every path starting from it eventually leads to a terminal (or another safe) node. The task is to return all safe nodes in ascending order.
Key Insights
- Identify cycles: Nodes involved in cycles are unsafe because there exists a path that does not terminate.
- DFS with state tracking: Use three states for each node (unvisited, visiting, and safe) to detect cycles.
- Memorization: Once a node's safety is determined, reuse this result to avoid redundant computations.
- Alternate approach: Reverse the graph and perform a topological sort, though DFS is more straightforward here.
Space and Time Complexity
Time Complexity: O(V + E) where V is the number of nodes and E is the number of edges.
Space Complexity: O(V) due to the recursion stack and additional storage for tracking node states.
Solution
We perform a depth-first search (DFS) and use an array to mark each node with one of three states:
- 0: unvisited
- 1: visiting (currently in recursion stack)
- 2: safe (confirmed safe node)
For each node, if during DFS a node is encountered that is already marked as visiting, a cycle is detected and the node is unsafe. If all reachable neighbors of a node are safe, then the node itself is safe. Finally, we collect and return all safe nodes sorted in ascending order.