Debugging challengeIntermediate
The DFS that died a thousand calls deep
Scenario
A connected-components counter passes every unit test — small random graphs, stars, cliques. On the first production input, a road network containing one long chain of 100,000 nodes, it dies with RecursionError: maximum recursion depth exceeded. The same algorithm in C++ handles the input fine. A teammate proposes sys.setrecursionlimit(10**9) as the fix. Evaluate that proposal, find the real issue, and fix it properly.
1def count_components(n, adj):2 visited = [False] * n3 4 def dfs(u):5 visited[u] = True6 for v in adj[u]:7 if not visited[v]:8 dfs(v)9 10 comps = 011 for u in range(n):12 if not visited[u]:13 comps += 114 dfs(u)15 return comps16 17 18n = 100_00019adj = [[] for _ in range(n)]20for i in range(n - 1): # one long path: 0 - 1 - 2 - ... - 9999921 adj[i].append(i + 1)22 adj[i + 1].append(i)23 24print(count_components(n, adj)) # RecursionError: maximum recursion depth exceededYour task
- What is Python's default recursion limit, and how deep does this DFS recurse on a path graph with
100,000nodes? - Why do small random graphs, stars and cliques all pass? What input *shape* triggers the failure?
- Evaluate
sys.setrecursionlimit(10**9): what does the limit actually protect, and what happens when you raise it far beyond the real stack? - Rewrite the DFS iteratively with an explicit stack. Where do you mark a node visited, and what goes wrong if you mark on pop instead of on push?
- Does the iterative version visit nodes in the same order as the recursive one? Does it matter here?
- State the complexity of the fixed version, including stack memory.
DebuggingImplementationEdge Cases
Work it out
Write your analysis before revealing anything. The self-check below compares it against what a strong answer contains.
Reveal
Progressive — each section builds on the previous one.
The bug
Why it happens
The fix
Edge cases
Complexity
Self-check
Tick what your analysis covered. Be honest — this feeds your readiness profile.