← Bank
DSA

BFS vs. DFS

DSAMid~12m
graphtraversalsearch

Prompt

We model our service dependencies as a graph and keep reaching for graph traversals — "what depends on this", "is there a dependency cycle", "fewest hops between two services". Walk me through how you'd pick BFS versus DFS for a problem like these, and what drives the choice.

How this round runs

This one's about reasoning, not reciting — I want you to commit to when each fits and defend it, and I'll hand you a concrete variant to see if your rule of thumb survives contact.

Model answer

Clarify first: directed or undirected? Weighted edges, or all hops equal? Could there be cycles, so I need visited-tracking to avoid looping? Roughly how wide versus deep is the graph — that drives the space trade-off.

Both are O(V + E) time. The real choice is shape and goal. BFS expands level by level with a queue, so the first time it reaches a node is along the fewest edges — that's why BFS gives shortest paths in an unweighted graph. DFS plunges down one branch with a stack or recursion and backtracks, which is the natural fit for "explore every path", topological ordering, and cycle detection. Space differs: BFS holds a whole frontier, up to O(V) and painful on a wide graph; DFS holds a single path, O(h) for depth h, but risks a deep recursion stack.

function bfs(start) {
  const queue = [start];
  const visited = new Set([start]);
  while (queue.length > 0) {
    const node = queue.shift();
    for (const nb of node.neighbors) {
      if (!visited.has(nb)) { visited.add(nb); queue.push(nb); }
    }
  }
}

function dfs(node, visited) {
  visited.add(node);
  for (const nb of node.neighbors) {
    if (!visited.has(nb)) dfs(nb, visited);
  }
}

So for "fewest hops between two services" I'd reach for BFS; for "is there a dependency cycle" I'd reach for DFS and track nodes on the current recursion path. Both need visited-tracking or they loop forever on a cyclic graph.

Signals — what a strong answer shows
  • Asked whether edges are weighted before claiming BFS gives shortest paths
  • Tied BFS to shortest-path/levels and DFS to cycles/topological order with reasons
  • Contrasted the space cost: O(V) frontier vs O(h) path
  • Flagged that both need visited-tracking on a cyclic graph
Follow-ups — where it goes next
  • Fewest hops between two services → BFS, and stop as soon as the target is dequeued
  • Detect a dependency cycle in a directed graph → DFS with an on-stack / in-progress marker, not just a visited set