LeetCode 104: Maximum Depth of Binary Tree Solution in Python Explained

Finding the maximum depth of a binary tree might feel like measuring the height of a towering structure, and LeetCode 104: Maximum Depth of Binary Tree is an easy-level challenge that makes it straightforward! Given the root of a binary tree, you need to return its maximum depth—the number of nodes along the longest path from root to leaf. In this blog, we’ll solve it with Python, exploring two solutions—Recursive DFS (our best solution) and Queue-Based BFS (a practical alternative). With step-by-step examples, detailed code breakdowns, and tips, you’ll master this problem. Let’s measure that depth!

Problem Statement

Section link icon

In LeetCode 104, you’re given the root of a binary tree. Your task is to return its maximum depth, defined as the number of nodes from the root to the farthest leaf, including both ends. This contrasts with zigzag traversal like LeetCode 103: Binary Tree Zigzag Level Order Traversal, focusing on depth rather than level-wise ordering.

Constraints

  • Number of nodes: 0 <= n <= 10^4
  • Node values: -100 <= Node.val <= 100

Example

Let’s see some cases:

Input: root = [3,9,20,null,null,15,7]
      3
     / \
    9  20
       / \
      15  7
Output: 3
Explanation: Longest path (3->20->15 or 3->20->7) has 3 nodes.
Input: root = [1,null,2]
      1
       \
        2
Output: 2
Explanation: Path 1->2 has 2 nodes.
Input: root = []
Output: 0
Explanation: Empty tree has depth 0.

These examples show we’re finding the longest root-to-leaf path.

Understanding the Problem

Section link icon

How do you solve LeetCode 104: Maximum Depth of Binary Tree in Python? Take root = [3,9,20,null,null,15,7]. We need the maximum depth—paths 3->20->15 and 3->20->7 both have 3 nodes, so return 3. For [1,null,2], depth is 2. This isn’t a symmetry check like LeetCode 101: Symmetric Tree; it’s about measuring tree height. We’ll use: 1. Recursive DFS: O(n) time, O(h) space—our best solution. 2. Queue-Based BFS: O(n) time, O(w) space—an alternative.

Let’s dive into the best solution.

Best Solution: Recursive DFS Approach

Section link icon

Explanation

Recursive DFS calculates the maximum depth by recursively computing the depth of each subtree—returning 0 for null nodes and 1 plus the maximum of left and right depths for non-null nodes. It’s the best solution due to its simplicity, efficiency, and natural fit for tree depth calculation, leveraging recursion to explore all paths.

For [3,9,20,null,null,15,7]:

  • Depth of 3 = 1 + max(depth(9), depth(20)).
  • Depth of 9 = 1, depth of 20 = 1 + max(depth(15), depth(7)) = 2.
  • Total = 1 + 2 = 3.

Step-by-Step Example

Assume a TreeNode class: class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val; self.left = left; self.right = right.

Example 1: root = [3,9,20,null,null,15,7]

Goal: Return 3.

  • Start: Call maxDepth(3).
  • Step 1: root = 3.
    • Left: maxDepth(9).
      • 9 has no children, return 1.
    • Right: maxDepth(20).
      • Left: maxDepth(15) → 1.
      • Right: maxDepth(7) → 1.
      • 20 depth = 1 + max(1, 1) = 2.
    • 3 depth = 1 + max(1, 2) = 3.
  • Finish: Return 3.

Example 2: root = [1,null,2]

Goal: Return 2.

  • Start: maxDepth(1).
  • Step 1: root = 1.
    • Left: maxDepth(None) → 0.
    • Right: maxDepth(2).
      • 2 has no children, return 1.
    • 1 depth = 1 + max(0, 1) = 2.
  • Finish: Return 2.

Example 3: root = []

Goal: Return 0.

  • Start: maxDepth(None).
  • Step 1: Null root, return 0.
  • Finish: Return 0.

How the Code Works (Recursive DFS) – Detailed Line-by-Line Explanation

Here’s the Python code with a thorough breakdown:

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def maxDepth(root: TreeNode) -> int:
    # Line 1: Base case - check if root is null
    if not root:
        # If root is None (e.g., empty tree or leaf’s child), depth is 0
        return 0

    # Line 2: Calculate left subtree depth
    left_depth = maxDepth(root.left)
    # Recursively gets depth of left child (e.g., 9 → 1)
    # Explores left subtree fully

    # Line 3: Calculate right subtree depth
    right_depth = maxDepth(root.right)
    # Recursively gets depth of right child (e.g., 20 → 2)
    # Explores right subtree fully

    # Line 4: Return maximum depth including current node
    return 1 + max(left_depth, right_depth)
    # Adds 1 for current node, takes max of subtrees
    # e.g., root=3, left=1, right=2 → 1 + max(1, 2) = 3

This detailed breakdown clarifies how recursive DFS efficiently computes the maximum depth.

Alternative: Queue-Based BFS Approach

Section link icon

Explanation

Queue-Based BFS processes the tree level-by-level, counting levels as it goes. Enqueue nodes with their depth, incrementing depth for each new level. It’s a practical alternative, using breadth-first traversal to measure height explicitly.

For [3,9,20,null,null,15,7]:

  • Level 1: [3].
  • Level 2: [9,20].
  • Level 3: [15,7].
  • Max depth = 3.

Step-by-Step Example (Alternative)

For [3,9,20,null,null,15,7]:

  • Start: queue = [(3, 1)], max_depth = 0.
  • Step 1: Pop (3,1), max_depth = 1, add (9,2), (20,2).
  • Step 2: Pop (9,2), max_depth = 2, no children.
  • Step 3: Pop (20,2), max_depth = 2, add (15,3), (7,3).
  • Step 4: Pop (15,3), max_depth = 3, no children.
  • Step 5: Pop (7,3), max_depth = 3, no children.
  • Finish: Return 3.

How the Code Works (BFS)

from collections import deque

def maxDepthBFS(root: TreeNode) -> int:
    if not root:
        return 0
    queue = deque([(root, 1)])
    max_depth = 0
    while queue:
        node, depth = queue.popleft()
        max_depth = max(max_depth, depth)
        if node.left:
            queue.append((node.left, depth + 1))
        if node.right:
            queue.append((node.right, depth + 1))
    return max_depth

Complexity

  • Recursive DFS:
    • Time: O(n) – visits each node once.
    • Space: O(h) – recursion stack, h = height.
  • Queue-Based BFS:
    • Time: O(n) – visits each node once.
    • Space: O(w) – queue size, w = max width.

Efficiency Notes

Recursive DFS is the best solution with O(n) time and O(h) space, offering a concise, efficient approach—Queue-Based BFS matches time complexity with O(w) space, providing a level-wise alternative that’s intuitive for breadth-first exploration.

Key Insights

  • Depth: Longest root-to-leaf path.
  • DFS: Recursive height calculation.
  • BFS: Level counting.

Additional Example

Section link icon

For root = [1,2,3,4,null,null,5]:

  • Goal: 3.
  • DFS: Depth of 1 = 1 + max(2’s depth=2, 3’s depth=1) = 3.

Edge Cases

Section link icon
  • Empty Tree: []0.
  • Single Node: [1]1.
  • Skewed Tree: [1,2,3]3.

Both solutions handle these well.

Final Thoughts

Section link icon

LeetCode 104: Maximum Depth of Binary Tree in Python is a fundamental tree challenge. The Recursive DFS solution stands out for its efficiency and simplicity, while Queue-Based BFS offers a breadth-first perspective. Want more? Try LeetCode 102: Binary Tree Level Order Traversal for level-wise traversal or LeetCode 94: Binary Tree Inorder Traversal for inorder basics. Ready to practice? Solve LeetCode 104 on LeetCode with [3,9,20,null,null,15,7], aiming for 3—test your skills now!