LeetCode 94: Binary Tree Inorder Traversal Solution in Python Explained

Traversing a binary tree might sound like a journey through a forest, and LeetCode 94: Binary Tree Inorder Traversal is an easy-level challenge that makes it a breeze! Given the root of a binary tree, you need to return its inorder traversal—a list of node values visited left, root, then right. In this blog, we’ll solve it with Python, exploring two solutions—Recursive Traversal (our primary, best approach) and Stack-Based Traversal (a powerful alternative). With step-by-step examples, detailed code breakdowns, and tips, you’ll master this problem. Let’s traverse that tree!

Problem Statement

Section link icon

In LeetCode 94, you’re given the root of a binary tree. Your task is to return the inorder traversal of its nodes’ values, visiting the left subtree, the root, then the right subtree. This differs from string partitioning like LeetCode 93: Restore IP Addresses, focusing on tree navigation.

Constraints

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

Example

Let’s see some cases:

Input: root = [1,null,2,3]
      1
       \
        2
       /
      3
Output: [1,3,2]
Explanation: Inorder: left (none), root (1), right (3 then 2).
Input: root = []
Output: []
Explanation: Empty tree, no nodes to traverse.
Input: root = [1]
Output: [1]
Explanation: Single node, just the root.

These examples show the inorder sequence: left, root, right.

Understanding the Problem

Section link icon

How do you solve LeetCode 94: Binary Tree Inorder Traversal in Python? Take root = [1,null,2,3]. We need [1,3,2]—visit left (none), root (1), right (2’s left: 3, then 2). This isn’t a linked list reversal like LeetCode 92: Reverse Linked List II; it’s about tree traversal. We’ll use: 1. Recursive Traversal: O(n) time, O(h) space—our best solution. 2. Stack-Based Traversal: O(n) time, O(h) space—an alternative.

Let’s dive into the primary solution.

Solution 1: Recursive Traversal Approach (Primary)

Section link icon

Explanation

Recursive Traversal leverages the natural structure of a binary tree, visiting the left subtree, the current node, then the right subtree in a depth-first manner. It’s the best solution due to its simplicity, readability, and alignment with inorder’s definition, making it ideal for most use cases.

For [1,null,2,3]:

  • No left, visit 1.
  • Right: 2, visit 2’s left (3), then 2.
  • Result: [1,3,2].

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 = [1,null,2,3]

Goal: Return [1,3,2].

  • Start: result = [], call inorder(root=1).
  • Step 1: root = 1.
    • Left: None, skip.
    • Visit: Append 1, result = [1].
    • Right: Call inorder(2).
  • Step 2: root = 2.
    • Left: Call inorder(3).
    • root = 3: No left/right, append 3, result = [1,3].
    • Visit: Append 2, result = [1,3,2].
    • Right: None, skip.
  • Finish: Return [1,3,2].

Example 2: root = []

Goal: Return [].

  • Start: result = [].
  • Step 1: root = None, return empty result.
  • Finish: Return [].

Example 3: root = [1]

Goal: Return [1].

  • Start: result = [].
  • Step 1: root = 1.
    • Left: None, skip.
    • Visit: Append 1, result = [1].
    • Right: None, skip.
  • Finish: Return [1].

How the Code Works (Recursive Traversal) – 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 inorderTraversal(root: TreeNode) -> list[int]:
    # Line 1: Initialize result list
    result = []
    # Starts as an empty list to store node values (e.g., [])
    # Will be populated during traversal

    # Line 2: Define helper function for recursion
    def inorder(node: TreeNode):
        # node = current node being processed (e.g., root=1 initially)

        # Line 3: Base case - check if node exists
        if not node:
            # If node is None (e.g., left of 1), return without action
            # Prevents errors and stops recursion at leaf ends
            return

        # Line 4: Traverse left subtree
        inorder(node.left)
        # Recursively visits the left child (e.g., node.left=None for root=1)
        # Ensures left subtree is fully explored first

        # Line 5: Visit current node
        result.append(node.val)
        # Adds current node’s value to result (e.g., append 1, result=[1])
        # Happens after left subtree, per inorder definition

        # Line 6: Traverse right subtree
        inorder(node.right)
        # Recursively visits the right child (e.g., node.right=2 for root=1)
        # Completes the inorder sequence: left, root, right

    # Line 7: Start traversal from root
    inorder(root)
    # Initiates the process with the root node (e.g., 1)
    # Builds result list through recursive calls

    # Line 8: Return the inorder traversal
    return result
    # Returns the final list (e.g., [1,3,2] for [1,null,2,3])
    # Contains all node values in inorder sequence

This detailed explanation ensures the recursive process is clear, making it the best choice for its elegance and efficiency.

Alternative: Stack-Based Traversal Approach

Section link icon

Explanation

Stack-Based Traversal uses a stack to mimic recursion, pushing nodes while moving left, then popping to visit and move right. It’s a strong alternative when avoiding recursion is preferred, offering explicit control over the traversal.

For [1,null,2,3]:

  • Push 1, no left, pop 1, visit 1.
  • Push 2, push 3, pop 3, visit 3, pop 2, visit 2.
  • Result: [1,3,2].

Step-by-Step Example (Alternative)

For [1,null,2,3]:

  • Start: stack = [], result = [], curr = 1.
  • Step 1: Push 1, no left, pop 1, append 1, curr = 2.
  • Step 2: Push 2, push 3, no left, pop 3, append 3.
  • Step 3: Pop 2, append 2, no right.
  • Finish: [1,3,2].

How the Code Works (Stack-Based)

def inorderTraversalStack(root: TreeNode) -> list[int]:
    result = []
    stack = []
    curr = root
    while curr or stack:
        while curr:
            stack.append(curr)
            curr = curr.left
        curr = stack.pop()
        result.append(curr.val)
        curr = curr.right
    return result

Complexity

  • Recursive Traversal:
    • Time: O(n) – visits each node once.
    • Space: O(h) – recursion stack, h = tree height.
  • Stack-Based Traversal:
    • Time: O(n) – visits each node once.
    • Space: O(h) – explicit stack size.

Efficiency Notes

Recursive Traversal is the best solution with O(n) time and O(h) space, leveraging Python’s call stack for simplicity and readability—Stack-Based Traversal matches the complexity but uses explicit memory, useful for deeper control or avoiding recursion limits.

Key Insights

  • Inorder Order: Left, root, right.
  • Recursion: Natural for trees.
  • Stack: Mimics recursion manually.

Additional Example

Section link icon

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

    1
   / \
  2   3
 / \
4   5
  • Goal: [4,2,5,1,3].
  • Recursive: Left (4,2,5), root (1), right (3).

Edge Cases

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

Both solutions handle these seamlessly.

Final Thoughts

Section link icon

LeetCode 94: Binary Tree Inorder Traversal in Python is a perfect intro to tree traversal. The Recursive Traversal solution shines with its clarity and efficiency, while Stack-Based Traversal offers a hands-on alternative. Want more? Try LeetCode 144: Binary Tree Preorder Traversal for a different order or LeetCode 92: Reverse Linked List II for list challenges. Ready to practice? Solve LeetCode 94 on LeetCode with [1,null,2,3], aiming for [1,3,2]—test your skills now!