Depth-First Search (DFS)

November 19, 2025
#dfs #depth-first-search #graph-traversal #algorithms #graph #recursion #interviewing

Introduction

Depth-First Search (DFS) is a fundamental graph traversal algorithm that explores as far as possible along each branch before backtracking. Think of it like exploring a maze by always taking the first path you see, going as deep as possible, then backtracking when you hit a dead end.

DFS is essential for detecting cycles, topological sorting, finding connected components, and solving maze/puzzle problems. Unlike BFS which uses a queue, DFS uses a stack (or recursion, which implicitly uses the call stack).

Review Graphs, Stacks, and Binary Trees first if needed.

How DFS works

DFS explores a graph in depth:

  1. Start at a source vertex
  2. Explore one neighbor completely before moving to the next
  3. Recursively visit unvisited neighbors
  4. Backtrack when no unvisited neighbors remain

Visual example:

Graph:
    A --- B --- E
    |     |
    C --- D

DFS from A (one possible order):
Visit A → go to B → go to E (dead end, backtrack)
       → back to B → go to D → go to C (already visited A)
       → back to D (dead end) → done

Order: A, B, E, D, C

DFS algorithm

Key components:

  • Stack: Maintains vertices to visit (LIFO) - or use recursion
  • Visited set: Tracks visited vertices to avoid cycles
  • Backtracking: Return to previous vertex when stuck

Steps:

  1. Mark starting vertex as visited
  2. For each unvisited neighbor:
    • Recursively visit that neighbor
  3. Backtrack when all neighbors are visited

DFS implementation

Recursive DFS on a graph

Iterative DFS using stack

DFS on a binary tree

Common DFS problems

1. Detect cycle in undirected graph

2. Find all paths from source to target

3. Topological sort (directed acyclic graph)

function topologicalSort(graph) {
  const visited = new Set();
  const stack = [];

  function dfs(vertex) {
    visited.add(vertex);

    for (const neighbor of graph.adjacencyList.get(vertex) || []) {
      if (!visited.has(neighbor)) {
        dfs(neighbor);
      }
    }

    stack.push(vertex); // Add to stack on the way back up
  }

  // Visit all vertices
  for (const vertex of graph.adjacencyList.keys()) {
    if (!visited.has(vertex)) {
      dfs(vertex);
    }
  }

  return stack.reverse(); // Reverse to get topological order
}

DFS vs BFS comparison

Feature DFS BFS
Data structure Stack/Recursion (LIFO) Queue (FIFO)
Order Depth first Level by level
Shortest path ❌ No ✅ Yes (unweighted)
Space O(height) O(width)
Use cases Cycle detection, topological sort, pathfinding Shortest path, level-order
Backtracking ✅ Natural ❌ Not typical

Complexity analysis

  • Time: O(V + E) where V = vertices, E = edges
  • Space:
    • Recursive: O(V) for call stack + visited set
    • Iterative: O(V) for explicit stack + visited set

Common pitfalls

  • Stack overflow: Deep recursion on large graphs
  • Not marking visited: Leads to infinite loops
  • Forgetting to backtrack: In path-finding problems
  • Confusing pre/post order: Know when to process vertices
  • Not handling disconnected components: May miss vertices

When to use DFS

  • Detecting cycles in graphs
  • Topological sorting of directed acyclic graphs
  • Finding connected components
  • Pathfinding with backtracking
  • Solving mazes and puzzles
  • Tree traversals (in-order, pre-order, post-order)
  • Generating permutations/combinations

Practice problems

  1. Clone a graph (DFS)
  2. Number of islands (2D grid DFS)
  3. Course schedule (detect cycle with DFS)
  4. Surrounded regions (capture regions on board)
  5. Pacific Atlantic water flow
  6. Longest increasing path in matrix
  7. Word search (backtracking with DFS)
  8. Validate binary search tree
  9. Path sum in binary tree
  10. Serialize and deserialize binary tree
  11. All paths from source to target
  12. Keys and rooms
  13. Reconstruct itinerary
  14. Employee importance (DFS on graph)
  15. Lowest common ancestor in binary tree

Complexity summary

  • Time: O(V + E) — visit each vertex and edge once
  • Space: O(V) — visited set and recursion stack/explicit stack

DFS is essential for graph problems requiring deep exploration, cycle detection, and backtracking. Master both DFS and BFS to handle the full range of graph and tree traversal problems.

Thanks for visiting
We are actively updating content to this site. Thanks for visiting! Please bookmark this page and visit again soon.
Sponsor