Cycle detection in graphs in Data Structures Theory - Time & Space Complexity
Start learning this pattern below
Jump into concepts and practice - no test required
When checking if a graph has a cycle, we want to know how the time needed grows as the graph gets bigger.
We ask: How does the work increase when the graph has more nodes and edges?
Analyze the time complexity of the following code snippet.
function hasCycle(graph) {
const visited = new Set();
const stack = new Set();
function dfs(node) {
if (stack.has(node)) return true;
if (visited.has(node)) return false;
visited.add(node);
stack.add(node);
for (const neighbor of graph[node]) {
if (dfs(neighbor)) return true;
}
stack.delete(node);
return false;
}
for (const node in graph) {
if (!visited.has(node)) {
if (dfs(node)) return true;
}
}
return false;
}
This code uses depth-first search to check if any path loops back to a node already in the current path, indicating a cycle.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The recursive depth-first search (DFS) visits each node and its neighbors.
- How many times: Each node and edge is checked once during the DFS traversal.
As the graph grows, the DFS visits more nodes and edges, so the work grows with both.
| Input Size (n nodes, m edges) | Approx. Operations |
|---|---|
| 10 nodes, 15 edges | About 25 checks (nodes + edges) |
| 100 nodes, 200 edges | About 300 checks |
| 1000 nodes, 3000 edges | About 4000 checks |
Pattern observation: The work grows roughly in proportion to the number of nodes plus edges.
Time Complexity: O(n + m)
This means the time needed grows linearly with the total number of nodes and edges in the graph.
[X] Wrong: "Cycle detection always takes quadratic time because of nested loops."
[OK] Correct: The DFS visits each node and edge once, so it does not repeatedly check all pairs, keeping the time linear.
Understanding how cycle detection scales helps you explain your approach clearly and shows you know how to handle bigger graphs efficiently.
"What if the graph is represented as an adjacency matrix instead of adjacency lists? How would the time complexity change?"
Practice
Solution
Step 1: Understand the concept of cycle detection
Cycle detection checks if a graph contains any loops where you can start at a node and return to it by following edges.Step 2: Identify the main goal
The main goal is to find if such loops exist, which can cause problems like infinite loops in algorithms.Final Answer:
To find if there is a loop in the graph -> Option BQuick Check:
Cycle detection = find loops [OK]
- Confusing cycle detection with sorting
- Thinking it counts nodes instead of finding loops
- Assuming it finds shortest paths
Solution
Step 1: Recall DFS cycle detection method
DFS explores nodes deeply and uses a recursion stack to track nodes currently in the path.Step 2: Identify the data structure used
A hash set or boolean array is used to track nodes in the recursion stack to detect back edges indicating cycles.Final Answer:
Hash Set to track recursion stack -> Option CQuick Check:
DFS cycle detection uses recursion stack tracking [OK]
- Using queue instead of stack for DFS
- Not tracking recursion stack nodes
- Confusing with BFS cycle detection
[(1, 2), (2, 3), (3, 4), (4, 2)]. Does this graph contain a cycle?Solution
Step 1: Trace the edges to find cycles
Edges form path 1->2->3->4 and then 4->2, which loops back to node 2.Step 2: Identify the cycle nodes
The cycle is formed by nodes 2, 3, and 4 because you can go from 2 to 3 to 4 and back to 2.Final Answer:
Yes, there is a cycle involving nodes 2, 3, and 4 -> Option AQuick Check:
Edges 4->2 create cycle 2-3-4 [OK]
- Ignoring the edge 4->2 that closes the cycle
- Thinking node 1's edges affect cycle
- Assuming no cycle if start node has no incoming edges
function dfs(node):
visited[node] = true
for neighbor in graph[node]:
if visited[neighbor]:
return true
if dfs(neighbor):
return true
return false
Solution
Step 1: Analyze the visited marking
The code marks nodes as visited but does not distinguish between nodes visited in current path and fully processed nodes.Step 2: Identify missing recursion stack tracking
Without tracking nodes in the current recursion stack, it cannot detect back edges properly, causing false negatives.Final Answer:
It does not track nodes in the current recursion stack -> Option AQuick Check:
Missing recursion stack tracking causes wrong cycle detection [OK]
- Using only visited array without recursion stack
- Confusing visited with recursion stack
- Thinking recursion depth causes error
Solution
Step 1: Understand task scheduling graph meaning
Edges show dependencies; a cycle means tasks depend on each other in a loop.Step 2: Identify the role of cycle detection
If a cycle exists, the schedule is impossible because tasks wait on each other endlessly.Final Answer:
It detects impossible schedules due to circular dependencies -> Option DQuick Check:
Cycle detection finds circular dependencies [OK]
- Thinking cycle detection sorts tasks
- Assuming cycles allow parallel tasks
- Confusing cycle detection with counting tasks
