You open a tree or graph problem on LeetCode and immediately think:
“Is this BFS or DFS?”
You vaguely remember rules from tutorials—“BFS for shortest path, DFS for recursion”—but in real problems the lines blur. You end up guessing, switching approaches halfway through, or trying both and getting lost in bugs.
This guide gives you a practical, experience-based decision framework for choosing between BFS and DFS on LeetCode, with clear examples, diagrams, and interview-focused strategies.
TL;DR
- Use BFS when you care about distance by steps/levels, the shortest path in an unweighted graph, or processing in layer order.
- Use DFS when you care about exploring full paths, backtracking, or structural properties like “is there a path/cycle/subtree satisfying X?”.
- Many problems can be solved with either; the better choice is the one that keeps your state, code, and reasoning simplest.
- Beginners often misuse DFS for shortest path, forget visited semantics in BFS/DFS, or mix recursion and mutable state incorrectly.
- You’ll learn a concrete decision checklist, visual mental models, and implementation templates to make BFS/DFS choices feel systematic instead of random.
Beginner-Friendly Intuition: How BFS and DFS “Think”
BFS: Wave-by-wave exploration
Breadth-first search explores nodes in layers:
Level 0: A
/ \
Level 1: B C
/ \ / \
Level 2: D E F GAt each step, BFS processes all nodes at the current distance before moving deeper:
- Level 0: A
- Level 1: B, C
- Level 2: D, E, F, G
It uses a queue and is ideal when:
- You need the shortest path (fewest edges) in an unweighted graph.
- You care about “distance in steps” (e.g., minimum moves, minimum days).
- You want the answer as soon as the first valid node is found.
DFS: Dive-deep exploration
Depth-first search goes as deep as possible along one path, then backtracks:
A → B → D (dead end) → backtrack → E → backtrack → C → F → GIt uses a stack (often via recursion) and is ideal when:
- You need to inspect or build entire paths.
- You care about structure: cycles, connectivity, subtree properties.
- You are doing backtracking: generating combinations, permutations, paths.
Step-by-Step Decision Framework
When you see a tree or graph problem, run this checklist:
Question 1: Do we care about shortest path / minimum steps?
If the problem asks for:
- Shortest path in an unweighted graph or grid
- Minimum number of moves / operations / transformations
- Minimum number of edges between two nodes
Then default to BFS.
Examples:
- “Minimum steps to transform word A to word B.”
- “Shortest path in a maze.”
- “Minimum number of operations to reach target.”
Question 2: Do we need all possible paths or combinations?
If you need:
- All paths from source to target
- All combinations / permutations / subsets
- To explore many possibilities and backtrack
Then default to DFS / backtracking.
Examples:
- “Find all paths from node 0 to node N-1.”
- “Generate all valid parentheses strings of length 2n.”
- “Find all paths that sum to target in a tree.”
Question 3: Is the graph/tree huge with simple yes/no answers?
If you only need:
- “Does any valid path exist?”
- “Is this graph connected?”
- “Does this graph contain a cycle?”
Then either BFS or DFS works. In practice:
- Use DFS when recursion is natural and depth isn’t too large.
- Use BFS when you want predictable memory and iteration.
At this point, you can choose whichever keeps the state simpler.
Question 4: Are we layering by time/rounds?
Problems that simulate time or rounds often map to BFS:
- “Number of minutes until all oranges rot.”
- “Min days to infect all nodes in a network.”
- “Spread from multiple sources at once.”
Think of BFS as simulating a multi-source wave. This aligns well with AI-guided LeetCode practice that visualizes levels step by step.
Visual Examples You Can Sketch in Interviews
Example 1: Shortest path in a grid → BFS
Problem sketch:
“Given a grid of 0s and 1s, find the shortest path from top-left to bottom-right, moving only up/down/left/right through 0s.”
Draw the grid and BFS layers:
Start at (0,0)
Layer 0: (0,0)
Layer 1: neighbors of (0,0)
Layer 2: neighbors of all nodes in layer 1
...As soon as you reach the target cell, you know you’ve found the shortest path (fewest steps).
Example 2: Count islands → DFS or BFS
Problem sketch:
“Count the number of islands in a grid.”
You don’t care about shortest path or distances. You care about exploring all reachable cells from each land cell.
You can:
- Use DFS to recursively explore each connected component.
- Or use BFS with a queue to explore neighbors.
Both work—choose the one that’s easier for you to implement correctly.
Code Example: BFS vs DFS Templates for a Grid
Let’s compare clean, minimal templates in TypeScript for a grid problem like “count number of islands”.
BFS template
function bfs(grid: string[][], startRow: number, startCol: number): void {
const rows = grid.length;
const cols = grid[0].length;
const queue: [number, number][] = [[startRow, startCol]];
grid[startRow][startCol] = "0"; // mark visited
const directions = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];
while (queue.length > 0) {
const [r, c] = queue.shift()!;
for (const [dr, dc] of directions) {
const nr = r + dr;
const nc = c + dc;
if (
nr >= 0 &&
nr < rows &&
nc >= 0 &&
nc < cols &&
grid[nr][nc] === "1"
) {
grid[nr][nc] = "0"; // mark visited
queue.push([nr, nc]);
}
}
}
}DFS template
function dfs(grid: string[][], r: number, c: number): void {
const rows = grid.length;
const cols = grid[0].length;
if (r < 0 || r >= rows || c < 0 || c >= cols || grid[r][c] !== "1") {
return;
}
grid[r][c] = "0"; // mark visited
dfs(grid, r + 1, c);
dfs(grid, r - 1, c);
dfs(grid, r, c + 1);
dfs(grid, r, c - 1);
}Both variants:
- Use a visited mechanism (mutating the grid).
- Explore all connected neighbors.
- Can be plugged into a double loop counting islands.
Practical Preparation Strategies
1. Build a tiny BFS/DFS note for yourself
In your notes or DSA learning path, keep:
- A 10–15 line BFS template.
- A 10–15 line DFS (recursive) template.
- 2–3 example problems where each shines.
Review this before graph-heavy interviews to keep syntax fresh.
2. Classify 20 problems by traversal type
Pick 20 LeetCode problems involving trees/graphs and label them:
- BFS, DFS, or “either”.
- Why you chose that pattern (shortest path vs structure vs enumeration).
This helps you recognize patterns quickly instead of guessing the approach each time.
3. Practice explaining your choice out loud
In interviews, don’t just say “I’ll use BFS.” Say:
“Because we need the shortest path in an unweighted graph, BFS over levels is a natural fit.”
Or:
“We only need to know whether any path exists, and recursion is natural on trees, so I’ll use DFS.”
A coding interview guide mindset helps you frame these justifications clearly.
4. Use interactive tools when stuck
When debugging traversal bugs, tools like LeetCopilot can support you by showing queue/stack contents step by step, helping you see where your visited logic or neighbor enumeration goes wrong.
Common Mistakes to Avoid
Mistake 1: Using DFS for shortest path in unweighted graphs
DFS can accidentally find a path that isn’t the shortest.
Fix: If the question is explicitly about “fewest steps” or “shortest path” without edge weights, default to BFS.
Mistake 2: Forgetting visited semantics
Symptoms:
- Infinite loops on cyclic graphs.
- Re-counting nodes / islands.
Fix: Always ask:
- Where do I mark nodes as visited?
- Do I mark upon enqueue (BFS) or upon dequeue, or at recursion entry (DFS)?
Be consistent.
Mistake 3: Blowing the recursion stack with DFS
Some inputs (deep trees, long chains) can cause stack overflow.
Fix:
- Use an explicit stack for DFS instead of recursion when depth might be large.
- Or choose BFS if it keeps depth shallower and implementation cleaner.
Mistake 4: Overcomplicating the state
Beginners often mix too much state into their traversal (path lists, counts, flags) in a way that’s hard to reason about.
Fix: Separate:
- Core traversal (queue/stack + visited).
- Problem-specific state (distance array, parent pointers, path sums).
FAQ
Q1: Can I always use BFS instead of DFS?
Not always. BFS can be more memory-heavy on wide graphs, and recursion-based DFS is often more natural for tree problems and backtracking. Use BFS for shortest paths and layer-based logic; use DFS when exploring full paths or structural properties.
Q2: How do I know if a problem is really a graph problem?
If you can think of elements as nodes with relationships (neighbors, prerequisites, edges), treat it as a graph. Even grids and course schedules are often graphs in disguise.
Q3: Is recursion bad in interviews?
No. Recursion is fine, especially for tree problems, as long as you handle base cases and stack depth safely. Just be ready to explain time/space complexity, including recursion stack space.
Q4: What should I practice before BFS/DFS-heavy interviews?
Do a focused week on trees/graphs: level order traversal, number of islands, shortest path in grid, cycle detection, and topological sort. Tools like mock interview simulator can then stress-test your traversal reasoning under time pressure.
Q5: How do I debug traversal bugs efficiently?
Log or visualize the queue/stack and visited set for small test cases. Check whether nodes are visited multiple times or never visited at all. Using an AI-guided LeetCode practice tool to step through state transitions can accelerate this feedback loop.
Conclusion
Choosing between BFS and DFS on LeetCode doesn’t have to be a coin flip.
The core guidelines:
- BFS for shortest paths, distances, and layer-by-layer simulations.
- DFS for path exploration, backtracking, and structural checks.
- Either is acceptable when the problem doesn’t care about distance—pick the one that makes your state and code simplest.
With a clear decision framework, a couple of small templates, and deliberate practice, you’ll stop guessing and start choosing traversals like a confident engineer rather than a nervous test-taker.
Want to Practice LeetCode Smarter?
LeetCopilot is a free browser extension that enhances your LeetCode practice with AI-powered hints, personalized study notes, and realistic mock interviews — all designed to accelerate your coding interview preparation.
Also compatible with Edge, Brave, and Opera
