BFS & DFS

Breadth-first and depth-first search are the two ways to explore a graph from a starting node. Both visit every reachable node in O(n + m); BFS also finds the fewest hops.

3 examples18 to practiceRead · 5 min
The idea

Both searches keep a list of places to go and a record of where they've been

To explore a graph from one node, you need two things: the nodes you have found but not explored yet, and a record of every node already found, so a loop in the graph can't send you round forever. Take a node from the first, look at its neighbors, add the new ones to both, and repeat until nothing is left to explore.

The only real choice is which found node to explore next. Take the oldest, with a queue, and you get breadth-first search (BFS): it spreads out evenly, one ring of distance at a time. Take the newest, with a stack (or with recursion, which uses the call stack), and you get depth-first search (DFS): it follows one route as far as it goes before backing up.

The rule

Mark a node as seen when you first find it, and explore each node once. Then BFS and DFS both cost O(n + m) for n nodes and m links: every node is taken once, and every neighbor list is read once.

Basic

BFS explores in rings, so it finds the fewest hops

BFS starts with the start node in a queue. Each node it takes from the front gives its unseen neighbors a distance one larger than its own and sends them to the back. Since the queue is first in, first out, every node 1 hop away is taken before any node 2 hops away, and so on.

That ring order is why BFS finds shortest routes when every link counts the same: the first time it reaches a node is along a route with the fewest hops. Once links carry different weights, hop counts are no longer enough, and you need Dijkstra's algorithm.

Medium

DFS goes as deep as it can, then backs up

DFS is natural to write with recursion: visiting a node means marking it, then visiting each unseen neighbor in turn. The call stack remembers the route back. Here the rooms are nodes and each key is a directed link; the question is whether room 0 reaches every room.

Room 5 was never entered: nobody holds its key. DFS reaches exactly what BFS would, in a different order. The recursion is as deep as the longest route it follows, so a graph shaped like a long chain of 100,000 nodes can overflow the call stack. Then write it with your own stack: push the start, and each round pop a node and push its unseen neighbors.

Hard

An outer loop over every node finds every connected component

One search only reaches the nodes connected to its start. A connected component is a largest group of nodes that can all reach each other; an undirected graph splits into one or more of them. To find them all, loop over every node and start a new search from each one not yet seen: each search marks one whole component.

This problem then asks which components are complete, with every pair linked. A complete component of k nodes has k × (k − 1) ÷ 2 links, so its neighbor lists hold k × (k − 1) entries in all.

The searches never overlap, because a seen node is never explored again. So the whole loop still costs O(n + m), however many components there are.

Choosing

Use BFS for fewest hops, DFS for anything about whole routes

BFS

DFS

Explores next

The oldest found node (a queue)

The newest found node (a stack or recursion)

Order

Ring by ring, by distance from the start

One route to its end, then back up

Finds

Fewest hops to every node

Reachability, components, every route, cycles

Memory

The widest ring

The longest route

Time

O(n + m)

O(n + m)

For "can I get there?" and "how many groups?" either works, and DFS is usually shorter to write. For "how few steps?", use BFS. The next page applies both to boards of cells, where the neighbors are the cells next door.

Check yourself

3 questions

1. BFS reaches node x for the first time from node u, which is 3 hops from the start. How far is x from the start?
2. A search marks nodes as seen when it takes them from the queue, not when it adds them. What goes wrong?
3. An undirected graph has 10 nodes and 3 links. At least how many connected components does it have?
Takeaways

Remember this

  • BFS and DFS both mark nodes as seen and explore each once: O(n + m).
  • BFS takes the oldest found node from a queue, so it explores in rings and finds the fewest hops.
  • DFS follows one route as deep as it goes, by recursion or with an explicit stack.
  • Looping over every node and searching from each unseen one finds every connected component.
Practice

Now solve some yourself

Only this topic 0 of 11 solved

  1. Easy
    Is there a route between two nodes?
    BFS & DFS
  2. Medium
    Count groups of friends from a matrix
    BFS & DFS
  3. Medium
    Fewest computers on a message route
    BFS & DFS
  4. Medium
    Fewest presses of double and minus one
    BFS & DFS
  5. Medium
    Signposts that lead every room to the exit fastest
    BFS & DFS
  6. Medium
    Jump left or right to reach a zero
    BFS & DFS
  7. Medium
    Find a round trip through cities
    BFS & DFS
  8. Medium
    Turn the fewest one-way roads toward city 0
    BFS & DFS
  9. Medium
    Pairs of nodes that can't reach each other
    BFS & DFS
  10. Medium
    Fewest hops when link colors must alternate
    BFS & DFS
  11. Medium
    Bombs that set each other off
    BFS & DFS

Mixed with topics you have practiced 0 unlocked

    7 more once you have practiced Recursion & backtracking, Hash tables & maps. Play one of its examples to the end and solve one of its problems to unlock them.

    Problems open on their own sites (LeetCode, Codeforces, CodeChef, AtCoder, CSES) in a new tab. Tick Solved when you get it accepted there; your ticks decide which mixed problems open next.

    Next

    Grid traversal

    Continue