← Back to DevBytes

Solving Maximum Depth of Binary Tree in JavaScript: Step-by-Step Guide

Solving Maximum Depth of Binary Tree in JavaScript: Step-by-Step Guide

The Maximum Depth of Binary Tree problem is one of the most foundational challenges you will encounter when learning tree data structures. It asks a deceptively simple question: What is the longest path from the root node down to the farthest leaf node? Despite its simplicity, mastering this problem unlocks a deeper understanding of recursion, traversal strategies, and algorithmic thinking that applies to countless other tree-based challenges.

What Is the Maximum Depth of a Binary Tree?

A binary tree is a hierarchical data structure where each node has at most two children, typically referred to as the left and right child. The maximum depth (also called the height) of a binary tree is the number of nodes along the longest path from the root node down to the farthest leaf node. By convention, an empty tree has a depth of 0, and a tree with only a root node has a depth of 1.

Consider the following binary tree:

      3
     / \
    9  20
       / \
      15  7

The longest path is 3 -> 20 -> 15 or 3 -> 20 -> 7, both of which contain 3 nodes. Therefore, the maximum depth is 3.

Why This Problem Matters

Understanding how to compute the maximum depth is essential for several reasons:

Defining the Binary Tree Node

Before solving the problem, we need a way to represent a binary tree in JavaScript. The standard approach is to define a TreeNode class:

class TreeNode {
  constructor(val, left = null, right = null) {
    this.val = val;
    this.left = left;
    this.right = right;
  }
}

Each node stores a value and references to its left and right children. We can construct the example tree above like this:

const root = new TreeNode(
  3,
  new TreeNode(9),
  new TreeNode(20, new TreeNode(15), new TreeNode(7))
);

Approach 1: Recursive Depth-First Search (DFS)

The most intuitive solution uses recursion. The key insight is that the maximum depth of a tree is 1 + max(depth(leftSubtree), depth(rightSubtree)). The base case occurs when the node is null, meaning we have reached beyond a leaf, so we return 0.

function maxDepth(root) {
  // Base case: an empty tree has depth 0
  if (root === null) {
    return 0;
  }

  // Recursively compute the depth of left and right subtrees
  const leftDepth = maxDepth(root.left);
  const rightDepth = maxDepth(root.right);

  // The depth of the current node is 1 plus the larger subtree depth
  return 1 + Math.max(leftDepth, rightDepth);
}

Let us trace through the example tree:

This approach has a time complexity of O(n), where n is the number of nodes, because we visit each node exactly once. The space complexity is O(h), where h is the height of the tree, due to the recursion stack. In the worst case (a skewed tree), this becomes O(n).

Approach 2: Iterative Depth-First Search Using a Stack

If you want to avoid recursion (perhaps to prevent stack overflow on very deep trees), you can simulate the same logic iteratively using an explicit stack. Each stack entry stores the current node and its accumulated depth.

function maxDepthIterativeDFS(root) {
  if (root === null) {
    return 0;
  }

  const stack = [[root, 1]];
  let maxDepthFound = 0;

  while (stack.length > 0) {
    const [node, depth] = stack.pop();

    if (node !== null) {
      maxDepthFound = Math.max(maxDepthFound, depth);
      stack.push([node.left, depth + 1]);
      stack.push([node.right, depth + 1]);
    }
  }

  return maxDepthFound;
}

Here, we push child nodes onto the stack along with their incremented depth. Whenever we pop a node, we update the maximum depth found so far. This preserves the O(n) time complexity and O(h) space complexity of the recursive version.

Approach 3: Iterative Breadth-First Search (BFS)

An alternative strategy processes the tree level by level. Each complete level we traverse increments the depth counter by one. When there are no more levels to process, the counter holds the maximum depth. This approach uses a queue.

function maxDepthBFS(root) {
  if (root === null) {
    return 0;
  }

  const queue = [root];
  let depth = 0;

  while (queue.length > 0) {
    const levelSize = queue.length;
    depth++;

    // Process all nodes at the current level
    for (let i = 0; i < levelSize; i++) {
      const currentNode = queue.shift();

      if (currentNode.left !== null) {
        queue.push(currentNode.left);
      }
      if (currentNode.right !== null) {
        queue.push(currentNode.right);
      }
    }
  }

  return depth;
}

The BFS approach is especially intuitive because depth directly corresponds to the number of levels processed. Its time complexity is also O(n), and its space complexity is O(w), where w is the maximum width of the tree. For a balanced tree, this can be more memory-efficient than DFS in certain scenarios, though for a skewed tree both degrade to O(n).

Comparing the Three Approaches

Best Practices

When implementing this solution in real projects or interviews, keep the following best practices in mind:

Testing the Solution

Here is a small test suite covering common scenarios:

function runTests() {
  // Test 1: Empty tree
  console.log(maxDepth(null) === 0 ? "PASS" : "FAIL");

  // Test 2: Single node
  console.log(maxDepth(new TreeNode(1)) === 1 ? "PASS" : "FAIL");

  // Test 3: Balanced tree
  const balanced = new TreeNode(
    3,
    new TreeNode(9),
    new TreeNode(20, new TreeNode(15), new TreeNode(7))
  );
  console.log(maxDepth(balanced) === 3 ? "PASS" : "FAIL");

  // Test 4: Left-skewed tree
  const leftSkewed = new TreeNode(1, new TreeNode(2, new TreeNode(3)));
  console.log(maxDepth(leftSkewed) === 3 ? "PASS" : "FAIL");

  // Test 5: Right-skewed tree
  const rightSkewed = new TreeNode(1, null, new TreeNode(2, null, new TreeNode(3)));
  console.log(maxDepth(rightSkewed) === 3 ? "PASS" : "FAIL");
}

runTests();

Running these tests confirms that the recursive solution handles all major tree shapes correctly. You can swap in the iterative implementations to verify they produce identical results.

Common Pitfalls to Avoid

Conclusion

The Maximum Depth of Binary Tree problem is a perfect entry point into the world of tree algorithms. By exploring recursive DFS, iterative DFS, and iterative BFS, you gain a versatile toolkit that transfers directly to more complex challenges like computing tree diameter, checking balance, and finding lowest common ancestors. The recursive solution remains the gold standard for its elegance and readability, while the iterative variants demonstrate how to reason about traversal without relying on the call stack. Master this problem, and you will have built a solid foundation for tackling virtually any tree-based question that comes your way in both interviews and real-world development.

— Ad —

Google AdSense will appear here after approval

← Back to all articles