Skip to content

136. Invert Binary Tree

πŸ”— LeetCode Problem: 226. Invert Binary Tree
πŸ“Š Difficulty: Easy
🏷️ Topics: Binary Trees, Recursion, DFS, BFS, Tree Transformation

Problem Statement

Given the root of a binary tree, invert the tree, and return its root.

Example 1:

Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]

Example 2:

Input: root = [2,1,3]
Output: [2,3,1]

Example 3:

Input: root = []
Output: []

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


🌳 Visual Understanding - Drawing the Transformation!

What Does "Invert" Mean?

"Invert" = "Mirror" = "Flip horizontally"

Every node swaps its left and right children!

Original:           Inverted:
    4                   4
   / \                 / \
  2   7      β†’        7   2
 / \ / \             / \ / \
1  3 6  9           9  6 3  1

Think of it as looking at the tree in a mirror!

Example 1: Complete Inversion

BEFORE:
              4                 Level 0
            /   \
           2     7              Level 1
          / \   / \
         1   3 6   9            Level 2

AFTER:
              4                 Level 0 (root stays same position)
            /   \
           7     2              Level 1 (2 and 7 swapped!)
          / \   / \
         9   6 3   1            Level 2 (all pairs swapped!)

What happened at each node:
  Node 4: swap(left=2, right=7) β†’ left=7, right=2
  Node 2: swap(left=1, right=3) β†’ left=3, right=1
  Node 7: swap(left=6, right=9) β†’ left=9, right=6
  Node 1: no children, nothing to swap
  Node 3: no children, nothing to swap
  Node 6: no children, nothing to swap
  Node 9: no children, nothing to swap

Example 2: Simple Case

BEFORE:
    2
   / \
  1   3

AFTER:
    2
   / \
  3   1

Node 2: swap(left=1, right=3) β†’ left=3, right=1

Edge Cases:

Case 1: Empty tree
  Input: null
  Output: null
  Nothing to invert!

Case 2: Single node
  Input:  5
  Output: 5
  No children to swap!

Case 3: Only left child
  BEFORE:    AFTER:
     1         1
    /           \
   2             2

  Swap left (2) with right (null)
  Result: right becomes 2, left becomes null

Case 4: Only right child
  BEFORE:    AFTER:
     1         1
      \       /
       2     2

  Swap left (null) with right (2)
  Result: left becomes 2, right becomes null

🧠 The AHA Moment - Recursive Insight!

The Key Question:

"How do I invert a tree?"

Recursive Breakdown:

To invert a tree:
  1. Invert the LEFT subtree
  2. Invert the RIGHT subtree
  3. SWAP left and right

Why does this work?

       4
      / \
     2   7

Step 1: Invert left subtree (2)
  β†’ Returns inverted version of subtree rooted at 2

Step 2: Invert right subtree (7)
  β†’ Returns inverted version of subtree rooted at 7

Step 3: Swap them
  β†’ Now 7 is on left, 2 is on right

Result:
       4
      / \
     7   2

Perfect! The tree at node 4 is now inverted!

Visual Example - Bottom Up:

Original Tree:
       4
      / \
     2   7
    / \ / \
   1  3 6  9

How recursion works (bottom-up):

Level 2 (leaves):
  Invert(1): No children β†’ return 1
  Invert(3): No children β†’ return 3
  Invert(6): No children β†’ return 6
  Invert(9): No children β†’ return 9

Level 1:
  Invert(2):
    - Invert left (1) β†’ get 1
    - Invert right (3) β†’ get 3
    - Swap: left=3, right=1
    - Return node 2 (now inverted)

  Invert(7):
    - Invert left (6) β†’ get 6
    - Invert right (9) β†’ get 9
    - Swap: left=9, right=6
    - Return node 7 (now inverted)

Level 0:
  Invert(4):
    - Invert left (2) β†’ get inverted subtree
    - Invert right (7) β†’ get inverted subtree
    - Swap: left=7, right=2
    - Return node 4 (fully inverted!)

Result:
       4
      / \
     7   2
    / \ / \
   9  6 3  1

🧠 Recursive Thinking - Building the Solution

Base Case:

What's the simplest tree to invert?
  β†’ A null tree (or empty tree)

What's the inversion of null?
  β†’ Still null!

Base Case:
  if (root == null) return null;

Also works for:
  - Empty tree
  - Leaf nodes (after processing their null children)

Recursive Case:

For any node:
  1. Recursively invert LEFT subtree
     left = invertTree(root.left)

  2. Recursively invert RIGHT subtree
     right = invertTree(root.right)

  3. SWAP the children
     root.left = right
     root.right = left

  4. Return the node
     return root

Why return root?
  Parent needs the inverted subtree!

The Complete Logic:

invertTree(node):
  if node is null:
    return null

  // Get inverted subtrees
  left = invertTree(node.left)
  right = invertTree(node.right)

  // Swap them
  node.left = right
  node.right = left

  // Return inverted tree
  return node

🎯 Solution 1: Recursive DFS (Post-order)

Implementation:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        // Base Case: null tree stays null
        if (root == null) {
            return null;
        }

        // Recursive Step 1: Invert left subtree
        // WHY? Need to flip all descendants before swapping
        TreeNode left = invertTree(root.left);

        // Recursive Step 2: Invert right subtree
        // WHY? Need to flip all descendants before swapping
        TreeNode right = invertTree(root.right);

        // Swap the children
        // WHY? This is what "inverting" means!
        root.left = right;
        root.right = left;

        // Return the inverted tree rooted at this node
        // WHY? Parent needs the inverted subtree
        return root;
    }
}

Alternative: Swap First (Pre-order)

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }

        // Swap children FIRST
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;

        // Then invert the subtrees
        // Note: root.left now points to original right!
        invertTree(root.left);
        invertTree(root.right);

        return root;
    }
}

Ultra-Concise Version:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) return null;

        // Swap and recurse in one go!
        TreeNode temp = root.left;
        root.left = invertTree(root.right);
        root.right = invertTree(temp);

        return root;
    }
}

πŸ” Detailed Dry Run with Recursion Visualization

Tree:
    2
   / \
  1   3

Complete Recursion Flow (Post-order):

CALL STACK VISUALIZATION:

Level 0: invertTree(2)
β”‚
β”œβ”€ root = 2, not null βœ“
β”‚
β”œβ”€ Invert LEFT: invertTree(1) ──────────┐
β”‚                                        β”‚
β”‚  Level 1: invertTree(1)               β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ root = 1, not null βœ“             β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ Invert LEFT: invertTree(null)    β”‚
β”‚  β”‚  β”‚                                 β”‚
β”‚  β”‚  └─ return null                   β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ left = null                       β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ Invert RIGHT: invertTree(null)   β”‚
β”‚  β”‚  β”‚                                 β”‚
β”‚  β”‚  └─ return null                   β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ right = null                      β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ Swap: left=null, right=null      β”‚
β”‚  β”‚  (nothing changes)                 β”‚
β”‚  β”‚                                     β”‚
β”‚  └─ return node 1                     β”‚
β”‚                                        β”‚
β”œβ”€ left = node 1                        β”‚
β”‚                                        β”‚
β”œβ”€ Invert RIGHT: invertTree(3) ─────────┐
β”‚                                        β”‚
β”‚  Level 1: invertTree(3)               β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ root = 3, not null βœ“             β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ Invert LEFT: invertTree(null)    β”‚
β”‚  β”‚  β”‚                                 β”‚
β”‚  β”‚  └─ return null                   β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ left = null                       β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ Invert RIGHT: invertTree(null)   β”‚
β”‚  β”‚  β”‚                                 β”‚
β”‚  β”‚  └─ return null                   β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ right = null                      β”‚
β”‚  β”‚                                     β”‚
β”‚  β”œβ”€ Swap: left=null, right=null      β”‚
β”‚  β”‚  (nothing changes)                 β”‚
β”‚  β”‚                                     β”‚
β”‚  └─ return node 3                     β”‚
β”‚                                        β”‚
β”œβ”€ right = node 3                       β”‚
β”‚                                        β”‚
β”œβ”€ NOW SWAP at root (2):                β”‚
β”‚  Before: root.left=1, root.right=3   β”‚
β”‚  After:  root.left=3, root.right=1   β”‚
β”‚                                        β”‚
└─ return node 2 (now inverted!)       β”‚

FINAL TREE:
    2
   / \
  3   1

Step-by-Step Visual Transformation:

Step 0: Original
    2
   / \
  1   3

Step 1: Process node 1 (leaf)
  No children to swap
    1

Step 2: Process node 3 (leaf)
  No children to swap
    3

Step 3: Process node 2 (root)
  Swap left (1) with right (3)

  Before:        After:
     2              2
    / \            / \
   1   3          3   1

DONE! βœ“

πŸ” Detailed Dry Run - Larger Tree

Tree:
       4
      / \
     2   7
    / \ / \
   1  3 6  9

Recursion Order (Post-order):

Call Order (DFS goes deep first):

1. invertTree(4) starts
   β”œβ”€ 2. invertTree(2) starts
   β”‚  β”œβ”€ 3. invertTree(1) starts
   β”‚  β”‚  β”œβ”€ 4. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ 5. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ Swap: no change
   β”‚  β”‚  └─ return node 1
   β”‚  β”œβ”€ 6. invertTree(3) starts
   β”‚  β”‚  β”œβ”€ 7. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ 8. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ Swap: no change
   β”‚  β”‚  └─ return node 3
   β”‚  β”œβ”€ Swap node 2: left=3, right=1
   β”‚  └─ return node 2 (inverted)
   β”‚
   β”œβ”€ 9. invertTree(7) starts
   β”‚  β”œβ”€ 10. invertTree(6) starts
   β”‚  β”‚  β”œβ”€ 11. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ 12. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ Swap: no change
   β”‚  β”‚  └─ return node 6
   β”‚  β”œβ”€ 13. invertTree(9) starts
   β”‚  β”‚  β”œβ”€ 14. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ 15. invertTree(null) β†’ return null
   β”‚  β”‚  β”œβ”€ Swap: no change
   β”‚  β”‚  └─ return node 9
   β”‚  β”œβ”€ Swap node 7: left=9, right=6
   β”‚  └─ return node 7 (inverted)
   β”‚
   β”œβ”€ Swap node 4: left=7, right=2
   └─ return node 4 (fully inverted!)

Total calls: 15 (7 actual nodes + 8 null checks)

Visual Transformation Steps:

Original:
       4
      / \
     2   7
    / \ / \
   1  3 6  9

After inverting subtree at 2:
       4
      / \
     2   7        ← Node 2's children swapped
    / \ / \
   3  1 6  9

After inverting subtree at 7:
       4
      / \
     2   7        ← Node 7's children swapped
    / \ / \
   3  1 9  6

After swapping at root 4:
       4
      / \
     7   2        ← Root's children swapped
    / \ / \
   9  6 3  1

DONE! βœ“

🎯 Solution 2: Iterative DFS (Using Stack)

Implementation:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();

            // Swap children
            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;

            // Push children to stack (if they exist)
            if (node.left != null) {
                stack.push(node.left);
            }
            if (node.right != null) {
                stack.push(node.right);
            }
        }

        return root;
    }
}

Dry Run - Iterative:

Tree:
    2
   / \
  1   3

Stack Operations:

Initial: stack = [2]

Iteration 1:
  Pop: 2
  Swap: 2's children (left=1, right=3) β†’ (left=3, right=1)
  Push: 3 (now on left), 1 (now on right)
  stack = [3, 1]

Iteration 2:
  Pop: 1
  Swap: 1's children (both null) β†’ no change
  Push: nothing (no children)
  stack = [3]

Iteration 3:
  Pop: 3
  Swap: 3's children (both null) β†’ no change
  Push: nothing (no children)
  stack = []

Stack empty β†’ Done!

Result:
    2
   / \
  3   1

🎯 Solution 3: BFS (Level Order)

Implementation:

class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();

            // Swap children
            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;

            // Add children to queue (if they exist)
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }

        return root;
    }
}

Dry Run - BFS:

Tree:
       4
      / \
     2   7
    / \ / \
   1  3 6  9

Level-by-level processing:

Level 0:
  queue = [4]
  Process 4: swap children (2,7) β†’ (7,2)
  Add: 7, 2
  queue = [7, 2]

Level 1:
  Process 7: swap children (6,9) β†’ (9,6)
  Add: 9, 6
  queue = [2, 9, 6]

  Process 2: swap children (1,3) β†’ (3,1)
  Add: 3, 1
  queue = [9, 6, 3, 1]

Level 2:
  Process 9: no children
  Process 6: no children
  Process 3: no children
  Process 1: no children
  queue = []

Done!

Result:
       4
      / \
     7   2
    / \ / \
   9  6 3  1

πŸ“Š Comparison: Recursive vs Iterative

Recursive DFS:

βœ“ Cleanest code (4-5 lines!)
βœ“ Most intuitive
βœ“ Natural tree traversal
βœ— Uses call stack (stack overflow for very deep trees)

Time: O(n)
Space: O(h) - recursion stack

Iterative DFS:

βœ“ Avoids recursion stack
βœ“ Same traversal as recursive
βœ— Slightly more code
βœ— Need to manage stack explicitly

Time: O(n)
Space: O(h) - explicit stack

BFS:

βœ“ Level-by-level intuition
βœ“ Processes tree systematically
βœ— More space for wide trees
βœ— Not as natural as recursion

Time: O(n)
Space: O(w) where w = max width

Which to Use?

For this problem: All work equally well!

Choose based on preference:
  - Want clean code? β†’ Recursive
  - Fear stack overflow? β†’ Iterative
  - Like level-order? β†’ BFS

My recommendation: Recursive (cleanest!)

πŸ“Š Complexity Analysis

Time Complexity: O(n)

Where n = number of nodes

Why?
  - Must visit every node exactly once
  - At each node: O(1) work (swap)
  - Total: n Γ— O(1) = O(n)

Can't do better than O(n):
  - Must touch every node to invert it!

Example:
  Tree with 7 nodes β†’ 7 visits
  Tree with 100 nodes β†’ 100 visits

Space Complexity:

Recursive: O(h)

Where h = height of tree

Why?
  - Recursion call stack depth
  - Maximum depth = height

Best case (balanced): O(log n)
  Example: Perfect tree with 15 nodes
  Height = 4 β†’ Stack depth = 4

Worst case (skewed): O(n)
  Example:
    1
   /
  2
 /
3
  Height = 3 β†’ Stack depth = 3

Iterative DFS: O(h)

Same as recursive
  - Stack holds nodes along one path
  - Maximum = height of tree

BFS: O(w)

Where w = maximum width of tree

Why?
  - Queue holds one level at a time
  - Maximum width level

Example:
       1
      / \
     2   3
    / \ / \
   4  5 6  7

  Level 3 has 4 nodes (w = 4)
  Queue holds up to 4 nodes

Worst case: w = n/2 (complete tree last level)
  Space: O(n)

⚠️ Common Mistakes

Mistake 1: Forgetting to Return Root

// ❌ WRONG - Doesn't return anything!
public TreeNode invertTree(TreeNode root) {
    if (root == null) return null;

    TreeNode left = invertTree(root.left);
    TreeNode right = invertTree(root.right);

    root.left = right;
    root.right = left;

    // Missing: return root;
}

// Function returns null by default in some languages!

// βœ“ CORRECT - Return the root
public TreeNode invertTree(TreeNode root) {
    // ... same code ...
    return root;  // Return the inverted tree!
}

Mistake 2: Swapping Without Saving

// ❌ WRONG - Lost reference!
root.left = root.right;   // Lost original left!
root.right = root.left;   // Now both point to same node!

// Result: Both children point to original right child!

// βœ“ CORRECT - Use temp variable
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;

Mistake 3: Not Handling Null

// ❌ WRONG - NullPointerException!
public TreeNode invertTree(TreeNode root) {
    TreeNode left = invertTree(root.left);  // Crash if root is null!
    // ...
}

// βœ“ CORRECT - Check null first
public TreeNode invertTree(TreeNode root) {
    if (root == null) return null;  // Handle null!
    // ...
}

Mistake 4: Only Swapping at Root

// ❌ WRONG - Only swaps top level!
public TreeNode invertTree(TreeNode root) {
    if (root == null) return null;

    TreeNode temp = root.left;
    root.left = root.right;
    root.right = temp;

    return root;  // Forgot to recurse!
}

// Tree:    2        Becomes:    2
//         / \                  / \
//        1   3                3   1
//       /                      \
//      4                        4  ← Didn't invert!

// βœ“ CORRECT - Recurse on subtrees
public TreeNode invertTree(TreeNode root) {
    if (root == null) return null;

    TreeNode temp = root.left;
    root.left = root.right;
    root.right = temp;

    invertTree(root.left);   // Recurse!
    invertTree(root.right);  // Recurse!

    return root;
}

Mistake 5: Confusing Pre-order and Post-order

// Both work, but must be consistent!

// βœ“ Pre-order (swap first):
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);   // Now points to original right!
invertTree(root.right);  // Now points to original left!

// βœ“ Post-order (swap last):
TreeNode left = invertTree(root.left);   // Invert first
TreeNode right = invertTree(root.right); // Invert first
root.left = right;   // Then swap
root.right = left;

// ❌ Mixed (swap between recurse):
TreeNode left = invertTree(root.left);
TreeNode temp = root.left;  // Confusing!
root.left = root.right;
// This gets messy!

🎯 Pattern Recognition - Tree Transformation

Core Pattern: Modify Tree Structure

Template for tree transformations:

TreeNode transform(TreeNode node) {
    // Base case: null
    if (node == null) return null;

    // Option 1: Pre-order (modify first, then recurse)
    modify(node);
    transform(node.left);
    transform(node.right);

    // Option 2: Post-order (recurse first, then modify)
    TreeNode left = transform(node.left);
    TreeNode right = transform(node.right);
    modify(node, left, right);

    return node;
}

1. Symmetric Tree (Problem 132)

Check if tree is mirror of itself
  - Uses inversion concept
  - But doesn't modify tree
  - Just compares

2. Flatten Binary Tree to Linked List

Transform tree to right-skewed list
  - Tree transformation
  - Modifies structure
  - Uses recursion

3. Convert BST to Greater Tree

Modify node values (not structure)
  - Tree transformation
  - Changes values, not pointers
  - Uses reverse in-order

4. Delete Node in BST

Remove node and restructure
  - Tree transformation
  - Complex pointer manipulation
  - Multiple cases

When to Use This Pattern:

βœ“ Modifying tree structure
βœ“ Swapping children
βœ“ Restructuring tree
βœ“ Converting tree format
βœ“ Tree rotations

πŸ“ Quick Revision Notes

🎯 Core Concept

Invert = Mirror = Swap left and right children at every node. Use recursion: (1) Invert left subtree, (2) Invert right subtree, (3) Swap them. Base case: null returns null. Each node returns itself after inversion (parent needs the reference). Can swap first (pre-order) or swap last (post-order) - both work!

⚑ Quick Implementation

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;

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;
    }

    public static TreeNode buildTree(Integer[] arr) {
        if (arr == null || arr.length == 0 || arr[0] == null) {
            return null;
        }

        TreeNode root = new TreeNode(arr[0]);
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        int i = 1;
        while (!queue.isEmpty() && i < arr.length) {
            TreeNode current = queue.poll();

            // Process left child
            if (i < arr.length) {
                if (arr[i] != null) {
                    current.left = new TreeNode(arr[i]);
                    queue.offer(current.left);
                }
                i++;
            }

            // Process right child
            if (i < arr.length) {
                if (arr[i] != null) {
                    current.right = new TreeNode(arr[i]);
                    queue.offer(current.right);
                }
                i++;
            }
        }

        return root;
    }

    public static void print(TreeNode root) {
        if (root == null) {
            System.out.println("[]");
            return;
        }

        List<String> result = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if (node != null) {
                result.add(String.valueOf(node.val));
                queue.offer(node.left);
                queue.offer(node.right);
            } else {
                result.add("null");
            }
        }

        while (!result.isEmpty() && result.get(result.size() - 1).equals("null")) {
            result.remove(result.size() - 1);
        }

        System.out.println(result);
    }    
}

class Solution {
  public TreeNode invertTree(TreeNode root) {
    // return recursiveDFS(root); // using normal recursion
    // return iterativeDFS(root); // using stack
    return iterativeBFS(root); // using queue
  }

  private TreeNode iterativeBFS(TreeNode root) {
    Queue<TreeNode> queue = new LinkedList<>();
    queue.offer(root);

    while (!queue.isEmpty()) {
      // We got a node.
      TreeNode curr = queue.poll();

      // Nothing to process. Ignore.
      if(curr == null) {
        continue;
      }

      // Swap its left and right children (incremental).
      TreeNode temp = curr.left;
      curr.left = curr.right;
      curr.right = temp;

      // Now, push its children onto the stack.
      queue.offer(curr.left);
      queue.offer(curr.right);
    }

    return root;
  }

  private TreeNode iterativeDFS(TreeNode root) {
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);

    while (!stack.isEmpty()) {      
      // We got a node.
      TreeNode curr = stack.pop();

      // Nothing to process. Ignore.
      if(curr == null) {
        continue;
      }

      // Swap its left and right children (incremental).
      TreeNode temp = curr.left;
      curr.left = curr.right;
      curr.right = temp;

      // Now, push its children onto the stack.
      stack.push(curr.left);
      stack.push(curr.right);
    }

    return root;
  }

  private TreeNode recursiveDFS(TreeNode root) {
    // base case: null/leaf node
    if(root == null) {
      return null;
    }

    // invert left and right separately.
    TreeNode left = invertTree(root.left);
    TreeNode right = invertTree(root.right);

    // Now swap them.
    root.left = right;
    root.right = left;

    // return the swapped one.
    return root;
  }

  public static void main(String[] args) {
    Solution s = new Solution();
    TreeNode res1 = s.invertTree(TreeNode.buildTree(new Integer[] {4,2,7,1,3,6,9}));
    TreeNode.print(res1); // [4,7,2,9,6,3,1]
  }
}

πŸ”‘ Key Insights

Why Recursion Works:

Tree:    4
        / \
       2   7

To invert tree at 4:
  1. Get inverted left subtree (2)
  2. Get inverted right subtree (7)
  3. Swap them!

Result:  4
        / \
       7   2

Each subtree handles its own inversion!
Trust the recursion! ✨

Pre-order vs Post-order:

Pre-order (swap first):
  - Swap children
  - Then recurse on NEW positions
  - root.left now points to original right!

Post-order (swap last):
  - Recurse on original positions
  - Get inverted subtrees back
  - Then swap them

Both work! Choose what's clearer to you.

Must Return Root:

Why return root?

Parent needs the reference!

If you don't return:
  - Parent loses connection to subtree
  - Tree gets disconnected

Always: return root at end!

πŸŽͺ Memory Aid

"Recurse on kids, then swap 'em!"
"Mirror means swap left and right!"
"Every node swaps, every level!"
"Don't forget to return root!" ✨

⚠️ Don't Forget

  • Return root at the end (parent needs it!)
  • Use temp variable for swapping (don't lose reference!)
  • Check null first (before accessing children)
  • Recurse on both sides (not just swap at root!)
  • Both pre and post-order work (be consistent!)
  • Swap means both directions (leftβ†’right AND rightβ†’left)

πŸ”— The Swap Pattern

// Classic swap with temp variable

TreeNode temp = root.left;
root.left = root.right;
root.right = temp;

// Why temp needed?
// Without it:
root.left = root.right;   // Lost original left!
root.right = root.left;   // Both point to same!

// With temp:
temp = root.left;         // Save left βœ“
root.left = root.right;   // Use right βœ“
root.right = temp;        // Restore left βœ“

πŸŽ‰ Congratulations!

You've mastered tree transformation!

What You Learned:

βœ… Tree inversion - Mirroring/flipping trees
βœ… Recursion for modification - Changing structure
βœ… Pre-order vs Post-order - When to modify
βœ… Return value importance - Parent needs reference
βœ… Swap technique - Using temp variable
βœ… Multiple approaches - Recursive, DFS, BFS

Pattern Evolution:

Problem 131-132: Tree Comparison
  - Read-only operations
  - Return boolean
  - Don't modify tree

Problem 133-135: Tree Calculation/Validation
  - Read-only operations
  - Return int/boolean
  - Don't modify tree

Problem 136: Tree Transformation
  - MODIFY tree structure βœ“
  - Return TreeNode
  - Change pointers

New skill unlocked: Tree modification!

The Famous Interview Story:

This problem is famous because:

Max Howell (creator of Homebrew) tweeted:
"Google: 90% of our engineers use the software you wrote (Homebrew), 
but you can't invert a binary tree on a whiteboard so fuck off."

Moral of the story:
  - Know this problem! πŸ˜„
  - It's a classic
  - Very common in interviews

You're now prepared! πŸ’ͺ

Next Steps:

Great problems to practice transformation: - Flatten Binary Tree (harder transformation) - Convert BST to Greater Tree (value modification) - Delete Node in BST (complex restructuring)

You're building powerful tree skills! πŸŒ³πŸ”„βœ¨