150NeetCode 150

47.Maximum Depth of Binary Tree

EasyBlind 75Trees ยท 2/15

Problem

Given the root of a binary tree, return its maximum depth โ€” the number of nodes along the longest path from the root down to the farthest leaf.

An empty tree has depth 0; a tree with only a root has depth 1.

Examples

Input:  root = [3,9,20,null,null,15,7]
Output: 3
Explanation: The longest root-to-leaf paths are 3 -> 20 -> 15 and 3 -> 20 -> 7, each with 3 nodes.
Input:  root = [1,null,2]
Output: 2
Input:  root = []
Output: 0

Constraints

  • The number of nodes in the tree is in the range [0, 10^4].
  • -100 <= Node.val <= 100

๐Ÿ’ก Key Insight

Depth satisfies a simple recurrence: depth(node) = 1 + max(depth(node.left), depth(node.right)), with depth(null) = 0. Equivalently, it is the number of levels a BFS walks through. Either way, each node is touched once, giving O(n).

Iterative DFS with a Stack

TimeO(n)SpaceO(h)

Intuition

Simulate the recursion explicitly: push (node, depthOfNode) pairs onto a stack. Every time a node is popped, its depth is a candidate for the answer, and its children are pushed with depth + 1.

Algorithm

  1. If root is null, return 0.
  2. Push (root, 1) onto two parallel stacks (nodes and depths).
  3. While the stack is not empty, pop (node, d), update max = max(max, d), and push non-null children with d + 1.
  4. Return max.

Visualization

stack: [(3,1)]                max = 1
pop (3,1)  push (9,2),(20,2)  max = 1
pop (20,2) push (15,3),(7,3)  max = 2
pop (7,3)                     max = 3
pop (15,3)                    max = 3
pop (9,2)                     max = 3   -> answer 3

Code

java
import java.util.ArrayDeque;
import java.util.Deque;

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Deque<TreeNode> nodes = new ArrayDeque<>();
        Deque<Integer> depths = new ArrayDeque<>();
        nodes.push(root);
        depths.push(1);
        int max = 0;
        while (!nodes.isEmpty()) {
            TreeNode node = nodes.pop();
            int depth = depths.pop();
            max = Math.max(max, depth);
            if (node.left != null) {
                nodes.push(node.left);
                depths.push(depth + 1);
            }
            if (node.right != null) {
                nodes.push(node.right);
                depths.push(depth + 1);
            }
        }
        return max;
    }
}

Complexity

  • Time: O(n) โ€” every node is pushed and popped once.
  • Space: O(h) โ€” the stack holds pending siblings along the current path; O(n) for a skewed tree.

Complexity Comparison

Approach Time Space
Iterative DFS with a Stack O(n) O(h)
BFS Level Counting O(n) O(w)
Recursive DFS O(n) O(h)

Common Pitfalls

  • Counting edges instead of nodes โ€” this problem counts nodes, so a single-node tree has depth 1, not 0.
  • Returning 1 for a null node, which adds a phantom level everywhere.
  • In BFS, reading queue.size() inside the loop condition instead of snapshotting it โ€” the size changes as children are enqueued, mixing levels.
  • With 10^4 nodes in a skewed tree, recursion depth reaches 10^4; it is fine on LeetCode, but iterative versions avoid stack overflow on much larger inputs.