Talentd
FleetCode
Make and follow sheets.Sign in

Find Eventual Safe States solution and explanation

MediumBreadth-First SearchDepth-First SearchGraphTopological Sort6 min read71.6% acceptanceUpdated 9 Apr 2026
G-20. Find Eventual Safe States - DFStake U forward · 23:43 · 318K viewsWatch on YouTube
9 more videos on this problem
  1. G-20. Find Eventual Safe States - DFStake U forward · 23:43 · 318K views
  2. G-25. Find Eventual Safe States - BFS - Topological Sorttake U forward · 16:57 · 298K views
  3. Find Eventual Safe States - Leetcode 802 - PythonNeetCode · 13:18 · 35K views
  4. Find Eventual Safe States | 2 Approaches | Intuition | Leetcode 802 | MICROSOFT | codestorywithMIKcodestorywithMIK · 33:54 · 20K views
  5. Find Eventual Safe States - Leetcode 802 - PythonNeetCodeIO · 13:18 · 9K views
  6. Find Eventual Safe States | Leetcode 802Techdose · 20:44 · 3K views
  7. Leetcode 802. Find Eventual Safe States. EnglishAlina L · 9:15 · 1K views
  8. 802. Find Eventual Safe StatesDeep Tech · 21:17 · 631 views
  9. 802. Find Eventual Safe States | Leetcode Daily ChallengeEthos Typos · 15:04 · 169 views
  10. LeetCode - 802. Find Eventual Safe States | DFS | JavaOrkhan Gasanov · 8:40 · 124 views

The problem

There is a directed graph of n nodes with each node labeled from 0 to n - 1. The graph is represented by a 0-indexed 2D integer array graph where graph[i] is an integer array of nodes adjacent to node i, meaning there is an edge from node i to each node in graph[i].

A node is a terminal node if there are no outgoing edges. A node is a safe node if every possible path starting from that node leads to a terminal node (or another safe node).

Return an array containing all the safe nodes of the graph. The answer should be sorted in ascending order.

Example 1:

Illustration of graph
Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output: [2,4,5,6]
Explanation: The given graph is shown above.
Nodes 5 and 6 are terminal nodes as there are no outgoing edges from either of them.
Every path starting at nodes 2, 4, 5, and 6 all lead to either node 5 or 6.

Example 2:

Input: graph = [[1,2,3,4],[1,2],[3,4],[0,4],[]]
Output: [4]
Explanation:
Only node 4 is a terminal node, and every path starting at node 4 leads to node 4.

Constraints:

  • n == graph.length
  • 1 <= n <= 104
  • 0 <= graph[i].length <= n
  • 0 <= graph[i][j] <= n - 1
  • graph[i] is sorted in a strictly increasing order.
  • The graph may contain self-loops.
  • The number of edges in the graph will be in the range [1, 4 * 104].

Approach overview

Problem Overview: You are given a directed graph where graph[i] lists all nodes reachable from node i. A node is considered eventually safe if every possible path starting from it ends at a terminal node (a node with no outgoing edges). Any node that can reach a cycle is unsafe. The task is to return all safe nodes in sorted order.

Approach 1: Reverse Graph and Topological Sort (O(V + E) time, O(V + E) space)

This approach converts the problem into a reverse topological process. First build the reverse graph so that every edge u → v becomes v → u. At the same time track the outdegree of each node in the original graph. Terminal nodes naturally have outdegree 0, so they are guaranteed safe. Push them into a queue and process them using a BFS-style topological sort. Every time you remove a safe node, decrease the outdegree of its predecessors in the reverse graph. If a predecessor’s outdegree becomes 0, it also becomes safe and enters the queue. The key insight: nodes that eventually lead only to safe nodes will lose all outgoing edges during this process. This solution is essentially a reversed topological sort applied to a graph, making it highly efficient and easy to reason about.

Approach 2: Depth-First Search with Safe Node Identification (O(V + E) time, O(V) space)

This method uses DFS to detect cycles and classify nodes. Maintain a state array with three states: unvisited, visiting, and safe. During DFS, mark the node as visiting. If you encounter another visiting node, a cycle exists and the path is unsafe. If all neighbors eventually lead to safe nodes, mark the current node as safe and return true. Memoization ensures each node is processed once. This is a classic cycle-detection pattern using Depth-First Search. The algorithm avoids recomputation by caching node states, giving linear complexity relative to nodes and edges.

Recommended for interviews: The reverse graph + topological sort solution is typically preferred. It clearly models the problem as eliminating nodes that cannot participate in cycles, and the BFS queue naturally reveals safe nodes. Interviewers often expect you to recognize the connection between cycle detection and topological processing. The DFS approach is also valid and demonstrates strong understanding of recursion and graph state tracking, but the topological strategy tends to be easier to explain and reason about under interview pressure.

Approach 1: Approach 1: Reverse Graph and Topological Sort

This approach utilizes the concept of reversing the graph and then performing a topological sort. Essentially, if we consider nodes leading to terminal nodes in the original graph, these nodes can be treated as terminal nodes in the reversed graph. We perform a topological sort to find such nodes.

By processing nodes which have no outgoing edges in the reversed graph (these correspond to safe nodes in the original graph), we can iteratively determine more nodes that are safe.

from collections import deque, defaultdict

def eventualSafeNodes(graph):
    G = defaultdict(list)
    rg = defaultdict(list)
    outdegree = [0] * len(graph)
    for u in range(len(graph)):
        for v in graph[u]:
            G[u].append(v)
            rg[v].append(u)
        outdegree[u] = len(graph[u])

    q = deque([])
    for i in range(len(graph)):
        if outdegree[i] == 0:
            q.append(i)

    res = []
    while q:
        u = q.popleft()
        res.append(u)
        for v in rg[u]:
            outdegree[v] -= 1
            if outdegree[v] == 0:
                q.append(v)

    return sorted(res)

graph = [[1, 2], [2, 3], [5], [0], [5], [], []]
print(eventualSafeNodes(graph))
import java.util.*;

class Solution {
    public List<Integer> eventualSafeNodes(int[][] graph) {
        // Implementation
        return new ArrayList<>();
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        int[][] graph = {{1, 2}, {2, 3}, {5}, {0}, {5}, {}, {}};
        List<Integer> result = sol.eventualSafeNodes(graph);
        System.out.println(result);
    }
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

void findEventualSafeNodes(int** graph, int graphSize, int* graphColSize, int* returnSize) {
    // Implementation
}

int main() {
    int n = 7;
    int graphColSize[] = {2, 2, 1, 1, 1, 0, 0};
    int graphData[7][2] = {{1, 2}, {2, 3}, {5}, {0}, {5}, {}, {}};
    int* graph[7];
    for (int i = 0; i < 7; i++) {
        graph[i] = graphData[i];
    }
    int returnSize = 0;
    findEventualSafeNodes(graph, 7, graphColSize, &returnSize);
    return 0;
}

This function utilizes BFS with reversed graph edges. Nodes with zero out-degree in the reversed graph are safe, and propagating this information allows identification of additional safe nodes.

Complexity

Time Complexity: O(V + E); Space Complexity: O(V + E), due to additional structures used to track reversed graph edges and node degrees.

Try this approach in the editor

Approach 2: Approach 2: Depth-First Search with Safe Node Identification

This approach adopts a classic depth-first search (DFS) to identify which nodes are safe. Safe nodes are marked during traversal.

We maintain a visited state for each node: unvisited, visiting, or safe. During DFS traversal, if we encounter a node marked as visiting, a cycle is detected, and the path is unsafe.

#include <vector>
#include <iostream>
using namespace std;

vector<int> eventualSafeNodes(vector<vector<int>>& graph) {
    // Implementation
    return {};
}

int main() {
    vector<vector<int>> graph = {{1, 2}, {2, 3}, {5}, {0}, {5}, {}, {}};
    vector<int> result = eventualSafeNodes(graph);
    for (int node : result) {
        cout << node << " ";
    }
    return 0;
}
var eventualSafeNodes = function(graph) {
    // Implementation
    return [];
};

let graph = [[1, 2], [2, 3], [5], [0], [5], [], []];
console.log(eventualSafeNodes(graph));
using System;
using System.Collections.Generic;

public class Solution {
    public IList<int> EventualSafeNodes(int[][] graph) {
        // Implementation
        return new List<int>();
    }

    public static void Main(string[] args) {
        Solution sol = new Solution();
        int[][] graph = new int[][] { new int[] { 1, 2 }, new int[] { 2, 3 }, new int[] { 5 }, new int[] { 0 }, new int[] { 5 }, new int[0], new int[0]};
        var result = sol.EventualSafeNodes(graph);
        Console.WriteLine(String.Join(", ", result));
    }
}

The function leverages DFS to maintain a status for each node: safe, unsafe, or unknown. It handles cycles efficiently by marking nodes actively being visited and recording safe nodes on successful completion of DFS for a node.

Complexity

Time Complexity: O(V + E), as each node and each edge is examined only once.

Space Complexity: O(V) for the recursion stack and state storage.

Try this approach in the editor

Approach 3: Default Approach

func eventualSafeNodes(graph [][]int) []int {
	n := len(graph)
	indeg := make([]int, n)
	rg := make([][]int, n)
	q := []int{}
	for i, vs := range graph {
		for _, j := range vs {
			rg[j] = append(rg[j], i)
		}
		indeg[i] = len(vs)
		if indeg[i] == 0 {
			q = append(q, i)
		}
	}
	for len(q) > 0 {
		i := q[0]
		q = q[1:]
		for _, j := range rg[i] {
			indeg[j]--
			if indeg[j] == 0 {
				q = append(q, j)
			}
		}
	}
	ans := []int{}
	for i, v := range indeg {
		if v == 0 {
			ans = append(ans, i)
		}
	}
	return ans
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Reverse Graph and Topological Sort

Time Complexity: O(V + E); Space Complexity: O(V + E), due to additional structures used to track reversed graph edges and node degrees.

Approach 2: Depth-First Search with Safe Node Identification

Time Complexity: O(V + E), as each node and each edge is examined only once.

Space Complexity: O(V) for the recursion stack and state storage.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Reverse Graph + Topological Sort (BFS)O(V + E)O(V + E)Best general solution. Efficient for detecting nodes not connected to cycles in directed graphs.
DFS with Safe Node MemoizationO(V + E)O(V)Useful when implementing recursive cycle detection or when DFS is already part of the solution.

Frequently asked questions

Is Find Eventual Safe States easy or hard?

Find Eventual Safe States is classified as a Medium problem. The main challenge is recognizing that nodes leading to cycles must be excluded and that reversing the graph allows a topological elimination process.

Find Eventual Safe States Python/Java solution

Most implementations build a reversed graph and perform a BFS topological sort. Python uses lists and collections.deque for the queue, while Java commonly uses ArrayList and ArrayDeque. Both implementations achieve O(V + E) time complexity.

How to solve Find Eventual Safe States in O(V + E)?

Build a reverse adjacency list and track the outdegree of every node. Start with nodes whose outdegree is zero (terminal nodes) and push them into a queue. Process them using BFS, reducing the outdegree of their predecessors. When a predecessor’s outdegree becomes zero, it becomes safe and enters the queue.

What is the best approach for Find Eventual Safe States?

Reverse graph with topological sort is the most common solution. By reversing edges and tracking node outdegrees, terminal nodes are processed first using a BFS queue. Nodes that eventually lose all outgoing edges become safe. This runs in O(V + E) time and is widely expected in interviews.

Is Find Eventual Safe States asked at Google/Amazon/Meta?

Graph cycle detection and topological sorting problems appear frequently at companies like Google, Amazon, and Meta. Variations of this problem are used to test understanding of directed graphs, dependency resolution, and cycle detection.

What data structure is used in Find Eventual Safe States?

The main structures are adjacency lists for the graph representation, a queue for BFS processing in the topological approach, and arrays for tracking node states or outdegrees. In the DFS version, recursion and a state array track visiting and safe nodes.

What is the time complexity of Find Eventual Safe States?

Both the topological sort and DFS approaches run in O(V + E) time, where V is the number of nodes and E is the number of edges. Each node and edge is processed at most once. Space complexity ranges from O(V) to O(V + E) depending on whether a reverse graph is stored.

Comments

Now write it yourselfClose this page and solve Find Eventual Safe States in the editor, without looking.
Practise Find Eventual Safe States