title: Invert Binary Tree
slug: invert-binary-tree
difficulty: easy
leetcode_id: 226
leetcode_url: https://leetcode.com/problems/invert-binary-tree/
categories:
  - trees
  - recursion
patterns:
  - tree-traversal
  - dfs
  - bfs

description: |
  Given the `root` of a binary tree, invert the tree, and return *its root*.

  Inverting a binary tree means swapping the left and right children of every node in the tree, creating a mirror image of the original structure.

constraints: |
  - The number of nodes in the tree is in the range `[0, 100]`
  - `-100 <= Node.val <= 100`

examples:
  - input: "root = [4,2,7,1,3,6,9]"
    output: "[4,7,2,9,6,3,1]"
    explanation: "The tree is inverted by swapping left and right children at every level. Node 4's children swap (2↔7), then node 7's children swap (6↔9) and node 2's children swap (1↔3)."
  - input: "root = [2,1,3]"
    output: "[2,3,1]"
    explanation: "The root's left child (1) and right child (3) are swapped."
  - input: "root = []"
    output: "[]"
    explanation: "An empty tree remains empty after inversion."

explanation:
  intuition: |
    Imagine holding a mirror up to a binary tree. The reflection you see is the inverted tree — every left branch becomes a right branch, and vice versa.

    The key insight is that **inverting a tree is a recursive operation**: to invert a tree rooted at any node, you simply swap its left and right children, then recursively invert each subtree. This naturally follows the structure of the tree itself.

    Think of it like this: if someone asked you to mirror-flip a family tree diagram, you'd swap each parent's children, then do the same for each of those children's subtrees. The operation is the same at every level — a perfect fit for recursion.

    The beauty of this problem is that the recursive solution directly mirrors the problem definition: invert the left subtree, invert the right subtree, then swap them.

  approach: |
    We solve this using a **Recursive (DFS) Approach**:

    **Step 1: Handle the base case**

    - If the node is `None`, return `None` immediately
    - This handles empty trees and serves as the recursion termination condition

    &nbsp;

    **Step 2: Swap the children**

    - Store the left child in a temporary variable (or use simultaneous assignment)
    - Assign the right child to the left
    - Assign the stored left child to the right
    - This mirrors the current node's immediate children

    &nbsp;

    **Step 3: Recursively invert subtrees**

    - Call `invert_tree` on the new left child (which was originally the right child)
    - Call `invert_tree` on the new right child (which was originally the left child)
    - This ensures all descendants are also inverted

    &nbsp;

    **Step 4: Return the root**

    - Return the current node after its subtree has been fully inverted
    - This allows the recursion to build back up correctly

    &nbsp;

    The order of swapping vs recursing doesn't matter — you can swap first then recurse, or recurse first then swap. Both produce the same result because every node gets visited and swapped exactly once.

  common_pitfalls:
    - title: Forgetting the Base Case
      description: |
        Without checking for `None`, your recursion will crash when it tries to access `.left` or `.right` on a null node.

        Always start recursive tree functions with:
        ```python
        if not root:
            return None
        ```
      wrong_approach: "Directly accessing root.left without null check"
      correct_approach: "Check if root is None before any operations"

    - title: Only Swapping at One Level
      description: |
        A common mistake is to swap the root's children but forget to recursively process the subtrees.

        For example, with `[4,2,7,1,3,6,9]`, only swapping at the root gives `[4,7,2,1,3,6,9]` — the grandchildren are in the wrong positions. You need to continue swapping at every level.
      wrong_approach: "Only swapping root.left and root.right"
      correct_approach: "Recursively invert both subtrees after swapping"

    - title: Overwriting Before Saving
      description: |
        If you write `root.left = root.right` first, you lose the original left child before you can assign it to the right.

        Use either a temporary variable or Python's simultaneous assignment:
        ```python
        root.left, root.right = root.right, root.left
        ```
      wrong_approach: "Sequential assignment without temp variable"
      correct_approach: "Simultaneous swap or use temporary variable"

  key_takeaways:
    - "**Recursive tree operations**: Many tree problems have elegant recursive solutions where you process subtrees and combine results"
    - "**Base case discipline**: Always handle the `None` case first in tree recursion"
    - "**Multiple valid approaches**: This can be solved with DFS (recursive or stack-based) or BFS (queue-based) — all with the same complexity"
    - "**Famous interview problem**: This problem gained notoriety when a senior engineer reportedly couldn't solve it on a whiteboard, highlighting that even simple problems require practice"

  time_complexity: "O(n). We visit each node exactly once to swap its children, where n is the number of nodes in the tree."
  space_complexity: "O(h). The recursion stack can grow to the height of the tree. In the worst case (skewed tree), this is O(n). For a balanced tree, it's O(log n)."

solutions:
  - approach_name: Recursive DFS
    is_optimal: true
    code: |
      class TreeNode:
          def __init__(self, val=0, left=None, right=None):
              self.val = val
              self.left = left
              self.right = right

      def invert_tree(root: TreeNode | None) -> TreeNode | None:
          # Base case: empty tree or leaf's null child
          if not root:
              return None

          # Swap the left and right children
          root.left, root.right = root.right, root.left

          # Recursively invert both subtrees
          invert_tree(root.left)
          invert_tree(root.right)

          # Return the root of the inverted tree
          return root
    explanation: |
      **Time Complexity:** O(n) — Each node is visited exactly once.

      **Space Complexity:** O(h) — Recursion stack depth equals tree height.

      This elegant solution directly mirrors the problem definition. We swap children at the current node, then recursively handle subtrees. The simultaneous assignment `root.left, root.right = root.right, root.left` safely swaps without needing a temporary variable.

  - approach_name: Iterative BFS
    is_optimal: true
    code: |
      from collections import deque

      def invert_tree(root: TreeNode | None) -> TreeNode | None:
          if not root:
              return None

          # Use a queue for level-order traversal
          queue = deque([root])

          while queue:
              # Process the next node
              node = queue.popleft()

              # Swap its children
              node.left, node.right = node.right, node.left

              # Add children to queue for processing
              if node.left:
                  queue.append(node.left)
              if node.right:
                  queue.append(node.right)

          return root
    explanation: |
      **Time Complexity:** O(n) — Each node is visited exactly once.

      **Space Complexity:** O(w) — Queue holds at most one level, where w is the maximum width of the tree. In the worst case (complete tree), this is O(n/2) = O(n).

      This iterative approach uses BFS to visit nodes level by level. At each node, we swap its children and add them to the queue. This avoids recursion stack overhead but uses explicit queue memory instead.

  - approach_name: Iterative DFS (Stack)
    is_optimal: true
    code: |
      def invert_tree(root: TreeNode | None) -> TreeNode | None:
          if not root:
              return None

          # Use a stack for depth-first traversal
          stack = [root]

          while stack:
              # Process the next node
              node = stack.pop()

              # Swap its children
              node.left, node.right = node.right, node.left

              # Add children to stack for processing
              if node.left:
                  stack.append(node.left)
              if node.right:
                  stack.append(node.right)

          return root
    explanation: |
      **Time Complexity:** O(n) — Each node is visited exactly once.

      **Space Complexity:** O(h) — Stack depth equals tree height in the worst case.

      This converts the recursive DFS to an iterative approach using an explicit stack. The logic is identical to the recursive version but avoids potential stack overflow for very deep trees. The order of processing differs from BFS but the final result is the same.
