Does the One-Way Network Contain a Circuit

Solve this Problem
Medium20–25 min
Topics
Companies

You are given a network of one-way roads as an adjacency list of a directed graph. Decide whether it contains a circuit: a route that follows the roads and comes back to the node it started from (a road from a node to itself also counts).

In a directed graph, meeting an already visited node is not enough to prove a circuit; the important thing is whether that node is still on the current search path.

Test Case 1:

Input:graph = [[1,4],[2],[3],[1],[5],[]]
Output:true
Explanation:Matrix rows (row u, column v is 1 when u → v): 0:[0,1,0,0,1,0], 1:[0,0,1,0,0,0], 2:[0,0,0,1,0,0], 3:[0,1,0,0,0,0], 4:[0,0,0,0,0,1], 5:all 0. The roads 1 → 2 → 3 → 1 close a circuit.

Test Case 2:

Input:graph = [[1,2],[2],[]]
Output:false
Explanation:Every road goes “forward”: nothing leads back, so there is no circuit.

Test Case 3:

Input:graph = [[0]]
Output:true
Explanation:A road from the node to itself is already a circuit.

Constraints

  • ◆1 ≤ n ≤ 10 nodes numbered 0 … n-1; graph[u] lists, in increasing order, every node v that has a one-way road u → v (adjacency-list form of a directed graph)
  • ◆There are no repeated roads; a road from a node to itself is allowed and counts as a circuit
  • ◆The graph may be disconnected
  • ◆A circuit is a route that follows the one-way roads and returns to the node it started from; return true if the graph contains one
🚀

Try the Dry Run

Don't just read the solution — watch it execute, one step at a time.

Approach & Solutions

Brute Force — Check Whether Each Node Can Return to Itself

Brute

A circuit exists exactly when some node can reach itself by following at least one road. So for every node, run a full search starting from the nodes it points to and see whether the search comes back to that node. n searches, each visiting up to n nodes and E roads: O(n · (n + E)). It is correct but repeats a lot of work.

TimeO(n · (n + E))
SpaceO(n)
1class Solution { 2 private boolean canReturn(int[][] graph, int start) { 3 boolean[] seen = new boolean[graph.length]; 4 Deque<Integer> stack = new ArrayDeque<>(); 5 for (int v : graph[start]) { 6 if (!seen[v]) { 7 seen[v] = true; 8 stack.push(v); 9 } 10 } 11 while (!stack.isEmpty()) { 12 int u = stack.pop(); 13 if (u == start) return true; 14 for (int w : graph[u]) { 15 if (!seen[w]) { 16 seen[w] = true; 17 stack.push(w); 18 } 19 } 20 } 21 return false; 22 } 23 24 public boolean hasCircuit(int[][] graph) { 25 for (int start = 0; start < graph.length; start++) { 26 if (canReturn(graph, start)) return true; 27 } 28 return false; 29 } 30}

Optimal — Depth-First Search With Three States

Optimal

Give each node a state: 0 = not seen yet, 1 = on the current search path (being explored), 2 = completely finished. When exploring node u, look at each road u → v: if v is in state 1, we have found a road back to a node that is still on our current path, which is a circuit. If v is in state 0, explore it. When all roads of u are handled, mark u finished (2). Finished nodes need not be searched again, so every node and road is handled once: O(n + E).

TimeO(n + E)
SpaceO(n)
1class Solution { 2 private boolean explore(int[][] graph, int node, int[] state) { 3 state[node] = 1; 4 for (int next : graph[node]) { 5 if (state[next] == 1) return true; 6 if (state[next] == 0 && explore(graph, next, state)) return true; 7 } 8 state[node] = 2; 9 return false; 10 } 11 12 public boolean hasCircuit(int[][] graph) { 13 int[] state = new int[graph.length]; 14 for (int start = 0; start < graph.length; start++) { 15 if (state[start] == 0 && explore(graph, start, state)) return true; 16 } 17 return false; 18 } 19}

Related Problems