Python 3.11+
The code uses standard Python syntax and containers supported by the browser Judge. The Depth-first Search proof does not depend on a minor Python release.
Verify in Python docs(opens in a new tab)Explore a branch completely before backtracking, using recursion or an explicit stack. Learn the algorithm's preconditions, state transition, correctness argument, Python cost model, and transfer from one focused drill to a full Interview Problem.
Recognize it when
Consider Depth-first Search when the prompt's constraints and required operations match this shape: Explore a branch completely before backtracking, using recursion or an explicit stack.

Sign in to save your code and progress across devices. The lesson and problem statement remain public.
Depth-first search commits to one neighbor path until it ends, then returns to the most recent unfinished choice. A recursive call stack or an explicit stack owns that frontier.
Each frame needs a node plus the state required below it: parent, depth, path aggregate, or traversal phase. State the return contract before descending so postorder work has a precise meaning.
def dfs_frame_trace(adjacency, start):
if start == -1: return []
trace = []
seen = set()
def visit(node, depth):
seen.add(node)
trace.append([node, depth])
for neighbor in adjacency[node]:
if neighbor not in seen:
visit(neighbor, depth + 1)
visit(start, 0)
return traceImplement dfs_frame_trace(adjacency, start). Return [node, depth] in recursive preorder, preserving neighbor order and visiting each node once.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
In a graph, add a node to visited before exploring neighbors. Marking afterward lets a cycle re-enter the same frame. Trees can sometimes use a parent pointer instead, but only when the input is guaranteed acyclic.
def component_size(adjacency, start):
if start == -1: return 0
seen = set()
stack = [start]
while stack:
node = stack.pop()
if node in seen: continue
seen.add(node)
stack.extend(adjacency[node])
return len(seen)Implement component_size(adjacency, start). Return the number of nodes reachable from start, or 0 for start -1.
Loading interactive editor.If it does not appear, the reference and starter code remain readable.Reload editor
Recursive DFS mirrors the proof and is concise; iterative DFS avoids Python recursion depth and makes traversal phases explicit. Push neighbors in reverse when an explicit stack must reproduce recursive neighbor order. Both take O(V + E).
Say: “This frame owns one node and this accumulated state. I mark before descending, each edge is considered a bounded number of times, and return means the entire branch is complete.” Include disconnected components and stack-space O(depth).
Python 3.11+
The code uses standard Python syntax and containers supported by the browser Judge. The Depth-first Search proof does not depend on a minor Python release.
Verify in Python docs(opens in a new tab)Interview bounds depend on the stated representation, input model, and real Python operations.
| Operation | Average | Worst | Interview note |
|---|---|---|---|
| Depth-first Search complete workflow | O(n) | O(n) | Depth-first traversal can carry one immutable scalar state down each branch and record it only at terminal nodes. The running total passed to a node equals the sum from the root through that node, independent of sibling branches. |
O(h) recursion depth plus output for the focused Carry State Through Tree DFS implementation.
These are the mistakes most likely to survive a happy-path example and fail a boundary case.
Verify algorithm preconditions such as sorted input, nonnegative weights, acyclicity, or admissible heuristics before applying it.
Prevent it: State and verify this precondition before coding: The graph or state space has an explicit neighbor relation and repeated states can be identified.
Avoid
def root_to_leaf_sums(values, children, root):
passUse instead
def root_to_leaf_sums(values, children, root):
if root == -1:
return []
sums = []
def visit(node, total):
total += values[node]
if not children[node]:
sums.append(total)
return
for child in children[node]:
visit(child, total)
visit(root, 0)
return sumsWhere you will hit this: Carry State Through Tree DFS(opens in a new tab)
Records the running sum at every internal node instead of only when a complete root-to-leaf path ends.
Prevent it: Preserve this proof obligation: Every reachable state enters the frontier under the traversal policy, while visited state prevents duplicate work.
Avoid
def root_to_leaf_sums(values, children, root):
if root == -1:
return []
sums = []
def visit(node, total):
total += values[node]
sums.append(total)
for child in children[node]:
visit(child, total)
visit(root, 0)
return sumsUse instead
def root_to_leaf_sums(values, children, root):
if root == -1:
return []
sums = []
def visit(node, total):
total += values[node]
if not children[node]:
sums.append(total)
return
for child in children[node]:
visit(child, total)
visit(root, 0)
return sumsWhere you will hit this: Carry State Through Tree DFS(opens in a new tab)
Include visited state, boundary cases, recursion depth, and hidden copying costs in correctness and complexity analysis.
Prevent it: Count every sort, slice, copy, membership check, heap update, and recursive frame before claiming O(n).
Avoid
def root_to_leaf_sums(values, children, root):
if root == -1:
return []
sums = []
def visit(node, total):
total += values[node]
sums.append(total)
for child in children[node]:
visit(child, total)
visit(root, 0)
return sumsUse instead
def root_to_leaf_sums(values, children, root):
if root == -1:
return []
sums = []
def visit(node, total):
total += values[node]
if not children[node]:
sums.append(total)
return
for child in children[node]:
visit(child, total)
visit(root, 0)
return sumsWhere you will hit this: Count Good Nodes in a Binary Tree(opens in a new tab)
Official Python documentation supports language behavior. Canonical problem pages provide additional practice context.
python-docs · checked 2026-07-27