Skip to content

Instantly share code, notes, and snippets.

@Ifihan
Created January 24, 2025 22:43
Show Gist options
  • Save Ifihan/5d9d6ec6f4f143c6b22310328eaef8c9 to your computer and use it in GitHub Desktop.
Save Ifihan/5d9d6ec6f4f143c6b22310328eaef8c9 to your computer and use it in GitHub Desktop.
Find Eventual Safe States

Question

Approach

My approach was by flipping the perspective of the graph. Instead of working with the original graph, I created a reversed graph, where edges point from their destination back to their source. This allows me to process nodes starting from the terminal ones (nodes with no outgoing edges), which are inherently safe.

Next, I calculated the out-degree for each node in the original graph, which represents the number of edges each node has. Nodes with an out-degree of 0 are terminal nodes, so I added them to a queue to process them first.

From there, I processed the queue. For each node, I marked it as safe and updated its neighbors in the reversed graph. If a neighbor’s out-degree dropped to 0, I added it to the queue since it had no remaining paths leading to unsafe nodes. This way, I worked backward, ensuring only nodes that eventually lead to terminal nodes were marked as safe.

Finally, I gathered all the safe nodes, sorted them, and returned the result.

Implementation

from collections import deque, defaultdict

class Solution:
    def eventualSafeNodes(self, graph: List[List[int]]) -> List[int]:
        n = len(graph)

        reverse_graph = defaultdict(list)
        in_degree = [0] * n

        for src in range(n):
            for dest in graph[src]:
                reverse_graph[dest].append(src)
            in_degree[src] = len(graph[src])

        queue = deque([i for i in range(n) if in_degree[i] == 0])
        safe_nodes = set(queue)

        while queue:
            node = queue.popleft()
            for neighbor in reverse_graph[node]:
                in_degree[neighbor] -= 1
                if in_degree[neighbor] == 0:
                    queue.append(neighbor)
                    safe_nodes.add(neighbor)

        return sorted(safe_nodes)

Complexities

  • Time: O(V + E) where V is the number of nodes (vertices) in the graph and E is the number of edges in the graph.
  • Space: O(V + E) where V is the number of nodes (vertices) in the graph and E is the number of edges in the graph.
image
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment