Skip to main content

Graph Traversal: BFS and DFS

A graph problem starts with a modeling decision: what is a vertex, what is an edge, and what makes two search states different? Choosing a queue or a stack comes after those decisions. Breadth-first search (BFS) explores distance layers; depth-first search (DFS) explores a branch before returning to other work.

FrontendInterviews.dev Updated

Recognize the Pattern

  • Connections, routes, dependencies, or grid neighbors describe a graph, even if the input never says graph.
  • Minimum numbers of equal-cost moves suggest BFS. Reachability or grouping can use either BFS or DFS.
  • A search state may include remaining obstacle eliminations, not just a cell position.

Core Invariant

In equal-cost BFS, the pending queue is ordered by nondecreasing distance. Marking a state at discovery schedules it once.

Important Boundary

BFS minimizes hops, not arbitrary edge costs. A visited key must include everything that changes the available next moves.

Graph rooted at 0, with vertices 1 and 2 at distance one and vertices 3, 4, and 5 at distance two.
From 0, the layers are [0], [1,2], then [3,4,5]. The extra edge 4-5 introduces a cycle without reducing those distances.

Model the state before the traversal

An adjacency list stores only existing edges. For an undirected connection, add both directions; for a dependency, preserve its direction. A grid can generate neighbors directly instead of materializing an adjacency list.

In a route-transfer problem, a bus route can be a vertex: boarding another route adds one to the answer. In obstacle elimination, reaching the same cell with more remaining eliminations is different from reaching it with none.

QuestionStarting choiceImportant boundary
Can I reach this vertex?BFS or DFSKeep a visited set.
Fewest equal-cost transitions?BFSFirst discovery fixes the distance.
Process children before parents?DFS with completion stateA plain stack is not automatically postorder.
Nonnegative, varying costs?Standard DijkstraRelax distances; first enqueue does not finalize them.
Negative edge weights?Bellman-Ford, or a suitable specialized algorithmDetect reachable negative cycles; affected targets may have no finite minimum.
Dependency ordering?Topological sortOnly a directed acyclic graph has a complete ordering.
Cycle in a directed graph?Active/finished DFS or Kahn's algorithmA single visited boolean does not distinguish an active ancestor.
Repeated component merges?Union findConnectivity is not a shortest path.

BFS: first discovery fixes the distance

The queue is ordered by nondecreasing distance. When a vertex is discovered from distance d, any shorter predecessor would already have been processed. Set its distance before enqueueing it, so two parents cannot schedule it twice.

Template Assumptions

  • Adjacency list with vertex IDs 0 through n - 1 and a valid source.
  • Each transition has equal cost; unreachable distances are -1.
JavaScript Template
function shortestDistances(neighbors, source) {
  const distance = new Array(neighbors.length).fill(-1);
  const queue = [source];
  distance[source] = 0;

  for (let head = 0; head < queue.length; head++) {
    const node = queue[head];
    for (const next of neighbors[node]) {
      if (distance[next] !== -1) continue;
      distance[next] = distance[node] + 1;
      queue.push(next);
    }
  }
  return distance;
}
  • The template expects an adjacency list and a valid source index. Unreachable vertices stay at -1.
  • A head index avoids repeatedly removing the first array entry. The backing array retains discovered vertices, so this template uses O(V) queue storage.
  • For multiple sources, enqueue all of them at distance zero before processing. Rotting Oranges uses this idea for simultaneous starting points.
  • A parent array can reconstruct a shortest path; distances alone cannot.

DFS: schedule reachable work with a stack

The stack gives recently scheduled work priority. This template returns a reachability traversal, not a shortest path or a finish-time ordering. Marking on push prevents duplicate scheduling in cyclic graphs.

Template Assumptions

  • Adjacency list with valid vertex IDs and a valid source.
  • Returns reachable vertices, not shortest distances or recursive completion order.
JavaScript Template
function reachableNodes(neighbors, source) {
  const seen = new Set([source]);
  const stack = [source];
  const order = [];

  while (stack.length) {
    const node = stack.pop();
    order.push(node);
    for (let i = neighbors[node].length - 1; i >= 0; i--) {
      const next = neighbors[node][i];
      if (seen.has(next)) continue;
      seen.add(next);
      stack.push(next);
    }
  }
  return order;
}
  • Neighbor order can change the returned order without changing the reachable set.
  • This mark-on-push stack need not produce the same DFS tree as recursive DFS. Low-link algorithms require explicit completion frames or recursive child returns.
  • For all connected components in an undirected graph, start a traversal from each still-unvisited vertex, sharing the visited set.
  • For directed cycle detection, distinguish active and finished vertices; one visited boolean is insufficient.

Trace the example, then change the invariant

Course Schedule and Foreign Dictionary add dependency ordering: Kahn's algorithm enqueues vertices whose indegree becomes zero. This is not the same queue invariant as shortest-distance BFS. Critical Connections instead tracks discovery and low-link values; neither basic template here is a bridge finder.

  1. Start at 0 with distance 0 and queue [0].
  2. Process 0: discover 1 and 2 at distance 1.
  3. Process 1: discover 3 and 4 at distance 2. Process 2: discover 5 at distance 2.
  4. The edge 4-5 finds an already discovered vertex, so it does not enqueue another copy. Distances are [0,1,1,2,2,2].

Step-by-Step: BFS queue and distance layers

Step 1 / 7
012345
Pending queue
[0]
distance[]
[0,-1,-1,-1,-1,-1]

Discover the source

Set distance[0] = 0 before enqueueing 0. Every other distance is still -1.

Complexity and failure modes

  • With adjacency lists, each reachable vertex is processed once and each reachable adjacency entry once: O(V + E) worst-case time.
  • Visited state, distances, and the explicit queue or stack use O(V) auxiliary space, excluding O(V + E) input storage.
  • Scanning an adjacency matrix costs O(V) per processed vertex, so a full traversal can cost O(V squared).
  • Backtracking is different: a visited state may need to be undone to explore another candidate. Do not reuse global reachability marking for Word Search.
  • Weighted scores, such as maximizing a path's minimum cell, need a different ordering or threshold argument; do not apply ordinary BFS just because the input is a grid.

Mistakes and Counterexamples

Use ordinary BFS to minimize varying edge costs.

Counterexample: S -> T costs 10, while S -> A -> T costs 1 + 1. The one-edge route is shorter in hops but costs more.

Correction: Use standard Dijkstra for nonnegative varying costs. Keep BFS for equal-cost transitions.

Mark a vertex only when removing it from the queue.

Counterexample: In the diamond 0 -> 1, 0 -> 2, 1 -> 3, 2 -> 3, both parents can enqueue 3 before either copy is processed.

Correction: Mark on enqueue to schedule each state once. Mark-on-dequeue can still be correct with duplicate-skipping, but does not prevent duplicate scheduling.

Treat every arrival at the same cell as equivalent.

Counterexample: One route reaches a junction with no eliminations left; another reaches it with one. If the exit crosses an obstacle, only the second arrival can finish.

Correction: Track (row, column, remaining budget), or prove a dominance rule that accounts for both distance and budget.

Last-Minute Recap

  • Define the state before the frontier.
  • BFS shortest-path claims require equal-cost transitions.
  • Mark at discovery; distinguish arrival from completion when the algorithm needs it.

Explain It in an Interview

  1. When would you choose BFS over DFS, and when can either work?
  2. Why can no later BFS arrival improve the distance in an equal-cost graph?
  3. How would obstacle eliminations change your visited state?

Ready to Apply This Pattern?

Before coding, explain why this pattern fits and what must stay true at each step. Start with an easier problem, then test that reasoning on a harder variation.

Ordered from Easy to Hard. Premium access requirements still apply.

16 problems
  1. 1.Number of IslandsCount components with one shared visited state across traversals.Medium
  2. 2.Clone GraphSeparate node identity from value; create each clone before visiting its neighbors.Medium
  3. 3.Rotting OrangesInitialize every starting point before advancing simultaneous minute layers.Medium
  4. 4.Course ScheduleDistinguish dependency ordering from shortest-distance BFS.Medium
  5. 5.Course Schedule IIProduce a dependency order and reject cycles rather than only reporting feasibility.Medium
  6. 6.Number of ProvincesCount connected components with shared visited state across all starting vertices.Medium
  7. 7.Cheapest Flights Within K StopsTrack cost and edges used separately; vertex-only visited state can discard a valid cheaper route.Medium
  8. 8.Jump Game III - Reachability SearchTreat indices as graph vertices and mark them before exploring both permitted jumps.Medium
  9. 9.Accounts MergeBuild connectivity through shared emails and compare graph traversal with disjoint sets.Medium
  10. 10.Bus RoutesChoose routes rather than stops as the unit whose distance counts boardings.Hard
  11. 11.Shortest Path in a Grid with Obstacles EliminationInclude the remaining elimination budget in the state, or justify dominance pruning.Hard
  12. 12.Foreign DictionaryInfer only the first differing character and detect invalid prefixes and cycles.Hard
  13. 13.Critical Connections in a NetworkTrack discovery and low-link values instead of reusing a basic visited boolean.Hard
  14. 14.Word LadderBuild an implicit word graph and use BFS layers to find the shortest transformation length.Hard
  15. 15.Word Ladder IIRetain every shortest-path predecessor, then reconstruct paths through the resulting DAG.Hard
  16. 16.Path With Maximum Minimum ValueTest threshold reachability and distinguish bottleneck scores from additive path costs.Hard

References