You are given a directed graph of n
nodes represented by an adjacency list, where graph[i]
is a list of nodes that node i
has edges to. A node is considered safe if and only if every possible path starting from that node leads to a terminal node (i.e., a node that has no outgoing edges). Return an array containing all the safe nodes of the graph. The answer should be sorted in ascending order.
Example:
Input: graph = [[1,2],[2,3],[5],[0],[5],[],[]]
Output: [2,4,5,6]
Explanation:
Node 5 and 6 are terminal nodes.
Node 2 and 4 lead to terminal nodes.
n
?
1 <= n <= 10^4
.To identify eventual safe nodes:
(u, v)
in the original graph becomes (v, u)
.from collections import deque, defaultdict
def eventualSafeNodes(graph):
n = len(graph)
# Reverse graph adjacency list
reverse_graph = defaultdict(list)
# Count of outbound edges for each node
outbound_count = [0] * n
for node, neighbors in enumerate(graph):
outbound_count[node] = len(neighbors)
for neighbor in neighbors:
reverse_graph[neighbor].append(node)
# Queue initialization with terminal nodes (nodes with 0 outbound edges)
queue = deque([node for node, count in enumerate(outbound_count) if count == 0])
safe_nodes = []
while queue:
current_node = queue.popleft()
safe_nodes.append(current_node) # Safe node found
for predecessor in reverse_graph[current_node]:
outbound_count[predecessor] -= 1 # Reduce outbound edges count
if outbound_count[predecessor] == 0:
queue.append(predecessor) # Add new terminal node to the queue
return sorted(safe_nodes)
# Test the function with an example input
graph = [[1,2],[2,3],[5],[0],[5],[],[]]
print(eventualSafeNodes(graph)) # Output: [2, 4, 5, 6]
O(V + E)
where V is the number of vertices and E is the number of edges.O(V + E)
operations.O(V log V)
for sorting the nodes.Total Time Complexity: O(V + E + V log V)
which simplifies to O(V log V + E)
.
Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?