Invert Binary Tree
Coding Challenge
easy
O(N)
O(H)
binary-treerecursiondfsbfstree-transformation
Language Selection
Choose your preferred programming language
Showing: Python
Problem Statement
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.
Input:
- Root of a binary tree
Output:
- Root of the inverted binary tree
Constraints:
- The number of nodes in the tree is in the range 0, 100
- -100 ≤ Node.val ≤ 100
Examples:
Example 1:
Original: Inverted:
4 4
/ \ / \
2 7 7 2
/ \ / \ / \ / \
1 3 6 9 9 6 3 1
Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]
Example 2:
Original: Inverted:
2 2
/ \ / \
1 3 3 1
Input: root = [2,1,3]
Output: [2,3,1]
Example 3:
Input: root = []
Output: []
Example 4:
Input: root = [1]
Output: [1]
Solutions
Approach 1: Recursive Solution
Use recursion to invert the tree by swapping left and right children at each node.
Algorithm:
- Base case: if node is null, return null
- Swap the left and right children of current node
- Recursively invert the left and right subtrees
- Return the current node
Python:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def invertTree(root):
"""
Recursive approach to invert binary tree
Time: O(N) where N is number of nodes
Space: O(H) where H is height of tree (recursion stack)
"""
if not root:
return None
# Swap left and right children
root.left, root.right = root.right, root.left
# Recursively invert subtrees
invertTree(root.left)
invertTree(root.right)
return root
def invertTreePostOrder(root):
"""
Post-order approach: invert children first, then swap
Time: O(N)
Space: O(H)
"""
if not root:
return None
# First invert the subtrees
left = invertTreePostOrder(root.left)
right = invertTreePostOrder(root.right)
# Then swap the children
root.left = right
root.right = left
return root
def invertTreeCompact(root):
"""
Most compact recursive solution
Time: O(N)
Space: O(H)
"""
if root:
root.left, root.right = invertTreeCompact(root.right), invertTreeCompact(root.left)
return root
Java:
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 {
/**
* Recursive approach to invert binary tree
* Time: O(N)
* Space: O(H)
*/
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
// Swap left and right children
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
// Recursively invert subtrees
invertTree(root.left);
invertTree(root.right);
return root;
}
/**
* Post-order approach: invert children first, then swap
* Time: O(N)
* Space: O(H)
*/
public TreeNode invertTreePostOrder(TreeNode root) {
if (root == null) {
return null;
}
// First invert the subtrees
TreeNode left = invertTreePostOrder(root.left);
TreeNode right = invertTreePostOrder(root.right);
// Then swap the children
root.left = right;
root.right = left;
return root;
}
/**
* Most compact recursive solution
* Time: O(N)
* Space: O(H)
*/
public TreeNode invertTreeCompact(TreeNode root) {
if (root != null) {
TreeNode temp = invertTreeCompact(root.left);
root.left = invertTreeCompact(root.right);
root.right = temp;
}
return root;
}
}
Go:
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// invertTree - Recursive approach to invert binary tree
// Time: O(N)
// Space: O(H)
func invertTree(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
// Swap left and right children
root.Left, root.Right = root.Right, root.Left
// Recursively invert subtrees
invertTree(root.Left)
invertTree(root.Right)
return root
}
// invertTreePostOrder - Post-order approach
// Time: O(N)
// Space: O(H)
func invertTreePostOrder(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
// First invert the subtrees
left := invertTreePostOrder(root.Left)
right := invertTreePostOrder(root.Right)
// Then swap the children
root.Left = right
root.Right = left
return root
}
// invertTreeCompact - Most compact recursive solution
// Time: O(N)
// Space: O(H)
func invertTreeCompact(root *TreeNode) *TreeNode {
if root != nil {
root.Left, root.Right = invertTreeCompact(root.Right), invertTreeCompact(root.Left)
}
return root
}
JavaScript:
class TreeNode {
constructor(val, left, right) {
this.val = (val === undefined ? 0 : val);
this.left = (left === undefined ? null : left);
this.right = (right === undefined ? null : right);
}
}
/**
* Recursive approach to invert binary tree
* Time: O(N)
* Space: O(H)
*/
function invertTree(root) {
if (!root) {
return null;
}
// Swap left and right children
[root.left, root.right] = [root.right, root.left];
// Recursively invert subtrees
invertTree(root.left);
invertTree(root.right);
return root;
}
/**
* Post-order approach: invert children first, then swap
* Time: O(N)
* Space: O(H)
*/
function invertTreePostOrder(root) {
if (!root) {
return null;
}
// First invert the subtrees
const left = invertTreePostOrder(root.left);
const right = invertTreePostOrder(root.right);
// Then swap the children
root.left = right;
root.right = left;
return root;
}
/**
* Most compact recursive solution
* Time: O(N)
* Space: O(H)
*/
function invertTreeCompact(root) {
if (root) {
[root.left, root.right] = [invertTreeCompact(root.right), invertTreeCompact(root.left)];
}
return root;
}
C#:
using System;
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val = 0, TreeNode left = null, TreeNode right = null) {
this.val = val;
this.left = left;
this.right = right;
}
}
public class Solution {
/// <summary>
/// Recursive approach to invert binary tree
/// Time: O(N)
/// Space: O(H)
/// </summary>
public TreeNode InvertTree(TreeNode root) {
if (root == null) {
return null;
}
// Swap left and right children
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
// Recursively invert subtrees
InvertTree(root.left);
InvertTree(root.right);
return root;
}
/// <summary>
/// Post-order approach: invert children first, then swap
/// Time: O(N)
/// Space: O(H)
/// </summary>
public TreeNode InvertTreePostOrder(TreeNode root) {
if (root == null) {
return null;
}
// First invert the subtrees
TreeNode left = InvertTreePostOrder(root.left);
TreeNode right = InvertTreePostOrder(root.right);
// Then swap the children
root.left = right;
root.right = left;
return root;
}
/// <summary>
/// Most compact recursive solution
/// Time: O(N)
/// Space: O(H)
/// </summary>
public TreeNode InvertTreeCompact(TreeNode root) {
if (root != null) {
TreeNode temp = InvertTreeCompact(root.left);
root.left = InvertTreeCompact(root.right);
root.right = temp;
}
return root;
}
}
Approach 2: Iterative Solution using Stack (DFS)
Use an explicit stack to perform depth-first traversal and invert nodes.
Algorithm:
- Use a stack to track nodes to process
- Push root onto stack
- While stack is not empty:
- Pop a node
- Swap its left and right children
- Push non-null children onto stack
Python:
def invertTreeIterative(root):
"""
Iterative approach using stack (DFS)
Time: O(N)
Space: O(H)
"""
if not root:
return None
stack = [root]
while stack:
node = stack.pop()
# Swap left and right 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
def invertTreePreOrder(root):
"""
Iterative pre-order traversal approach
Time: O(N)
Space: O(H)
"""
if not root:
return None
stack = [root]
while stack:
node = stack.pop()
# Process current node (swap children)
node.left, node.right = node.right, node.left
# Add children in reverse order for pre-order
if node.right: # This was originally left
stack.append(node.right)
if node.left: # This was originally right
stack.append(node.left)
return root
Java:
import java.util.Stack;
public TreeNode invertTreeIterative(TreeNode root) {
/**
* Iterative approach using stack (DFS)
* Time: O(N)
* Space: O(H)
*/
if (root == null) {
return null;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
// Swap left and right children
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add children to stack for processing
if (node.left != null) {
stack.push(node.left);
}
if (node.right != null) {
stack.push(node.right);
}
}
return root;
}
public TreeNode invertTreePreOrder(TreeNode root) {
/**
* Iterative pre-order traversal approach
* Time: O(N)
* Space: O(H)
*/
if (root == null) {
return null;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
// Process current node (swap children)
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add children in reverse order for pre-order
if (node.right != null) { // This was originally left
stack.push(node.right);
}
if (node.left != null) { // This was originally right
stack.push(node.left);
}
}
return root;
}
Go:
// invertTreeIterative - Iterative approach using stack (DFS)
// Time: O(N)
// Space: O(H)
func invertTreeIterative(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
stack := []*TreeNode{root}
for len(stack) > 0 {
node := stack[len(stack)-1]
stack = stack[:len(stack)-1]
// Swap left and right children
node.Left, node.Right = node.Right, node.Left
// Add children to stack for processing
if node.Left != nil {
stack = append(stack, node.Left)
}
if node.Right != nil {
stack = append(stack, node.Right)
}
}
return root
}
// invertTreePreOrder - Iterative pre-order traversal approach
// Time: O(N)
// Space: O(H)
func invertTreePreOrder(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
stack := []*TreeNode{root}
for len(stack) > 0 {
node := stack[len(stack)-1]
stack = stack[:len(stack)-1]
// Process current node (swap children)
node.Left, node.Right = node.Right, node.Left
// Add children in reverse order for pre-order
if node.Right != nil { // This was originally left
stack = append(stack, node.Right)
}
if node.Left != nil { // This was originally right
stack = append(stack, node.Left)
}
}
return root
}
JavaScript:
/**
* Iterative approach using stack (DFS)
* Time: O(N)
* Space: O(H)
*/
function invertTreeIterative(root) {
if (!root) {
return null;
}
const stack = [root];
while (stack.length > 0) {
const node = stack.pop();
// Swap left and right children
[node.left, node.right] = [node.right, node.left];
// Add children to stack for processing
if (node.left) {
stack.push(node.left);
}
if (node.right) {
stack.push(node.right);
}
}
return root;
}
/**
* Iterative pre-order traversal approach
* Time: O(N)
* Space: O(H)
*/
function invertTreePreOrder(root) {
if (!root) {
return null;
}
const stack = [root];
while (stack.length > 0) {
const node = stack.pop();
// Process current node (swap children)
[node.left, node.right] = [node.right, node.left];
// Add children in reverse order for pre-order
if (node.right) { // This was originally left
stack.push(node.right);
}
if (node.left) { // This was originally right
stack.push(node.left);
}
}
return root;
}
C#:
using System.Collections.Generic;
public TreeNode InvertTreeIterative(TreeNode root) {
/// <summary>
/// Iterative approach using stack (DFS)
/// Time: O(N)
/// Space: O(H)
/// </summary>
if (root == null) {
return null;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.Push(root);
while (stack.Count > 0) {
TreeNode node = stack.Pop();
// Swap left and right children
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add children to stack for processing
if (node.left != null) {
stack.Push(node.left);
}
if (node.right != null) {
stack.Push(node.right);
}
}
return root;
}
public TreeNode InvertTreePreOrder(TreeNode root) {
/// <summary>
/// Iterative pre-order traversal approach
/// Time: O(N)
/// Space: O(H)
/// </summary>
if (root == null) {
return null;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.Push(root);
while (stack.Count > 0) {
TreeNode node = stack.Pop();
// Process current node (swap children)
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add children in reverse order for pre-order
if (node.right != null) { // This was originally left
stack.Push(node.right);
}
if (node.left != null) { // This was originally right
stack.Push(node.left);
}
}
return root;
}
Approach 3: Iterative Solution using Queue (BFS)
Use level-order traversal (BFS) to invert the tree level by level.
Python:
from collections import deque
def invertTreeBFS(root):
"""
Iterative BFS approach using queue
Time: O(N)
Space: O(W) where W is maximum width of tree
"""
if not root:
return None
queue = deque([root])
while queue:
node = queue.popleft()
# Swap left and right 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
def invertTreeLevelOrder(root):
"""
Level-order approach that processes entire levels
Time: O(N)
Space: O(W)
"""
if not root:
return None
queue = deque([root])
while queue:
level_size = len(queue)
# Process entire level
for _ in range(level_size):
node = queue.popleft()
# Swap children
node.left, node.right = node.right, node.left
# Add next level nodes
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return root
Java:
import java.util.Queue;
import java.util.LinkedList;
public TreeNode invertTreeBFS(TreeNode root) {
/**
* Iterative BFS approach using queue
* Time: O(N)
* Space: O(W) where W is maximum width
*/
if (root == null) {
return null;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
// Swap left and right children
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add children to queue for processing
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return root;
}
public TreeNode invertTreeLevelOrder(TreeNode root) {
/**
* Level-order approach that processes entire levels
* Time: O(N)
* Space: O(W)
*/
if (root == null) {
return null;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int levelSize = queue.size();
// Process entire level
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
// Swap children
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add next level nodes
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
return root;
}
Go:
// invertTreeBFS - Iterative BFS approach using queue
// Time: O(N)
// Space: O(W) where W is maximum width
func invertTreeBFS(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
queue := []*TreeNode{root}
for len(queue) > 0 {
node := queue[0]
queue = queue[1:]
// Swap left and right children
node.Left, node.Right = node.Right, node.Left
// Add children to queue for processing
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
return root
}
// invertTreeLevelOrder - Level-order approach that processes entire levels
// Time: O(N)
// Space: O(W)
func invertTreeLevelOrder(root *TreeNode) *TreeNode {
if root == nil {
return nil
}
queue := []*TreeNode{root}
for len(queue) > 0 {
levelSize := len(queue)
// Process entire level
for i := 0; i < levelSize; i++ {
node := queue[0]
queue = queue[1:]
// Swap children
node.Left, node.Right = node.Right, node.Left
// Add next level nodes
if node.Left != nil {
queue = append(queue, node.Left)
}
if node.Right != nil {
queue = append(queue, node.Right)
}
}
}
return root
}
JavaScript:
/**
* Iterative BFS approach using queue
* Time: O(N)
* Space: O(W) where W is maximum width
*/
function invertTreeBFS(root) {
if (!root) {
return null;
}
const queue = [root];
while (queue.length > 0) {
const node = queue.shift();
// Swap left and right children
[node.left, node.right] = [node.right, node.left];
// Add children to queue for processing
if (node.left) {
queue.push(node.left);
}
if (node.right) {
queue.push(node.right);
}
}
return root;
}
/**
* Level-order approach that processes entire levels
* Time: O(N)
* Space: O(W)
*/
function invertTreeLevelOrder(root) {
if (!root) {
return null;
}
const queue = [root];
while (queue.length > 0) {
const levelSize = queue.length;
// Process entire level
for (let i = 0; i < levelSize; i++) {
const node = queue.shift();
// Swap children
[node.left, node.right] = [node.right, node.left];
// Add next level nodes
if (node.left) {
queue.push(node.left);
}
if (node.right) {
queue.push(node.right);
}
}
}
return root;
}
C#:
using System.Collections.Generic;
public TreeNode InvertTreeBFS(TreeNode root) {
/// <summary>
/// Iterative BFS approach using queue
/// Time: O(N)
/// Space: O(W) where W is maximum width
/// </summary>
if (root == null) {
return null;
}
Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root);
while (queue.Count > 0) {
TreeNode node = queue.Dequeue();
// Swap left and right children
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add children to queue for processing
if (node.left != null) {
queue.Enqueue(node.left);
}
if (node.right != null) {
queue.Enqueue(node.right);
}
}
return root;
}
public TreeNode InvertTreeLevelOrder(TreeNode root) {
/// <summary>
/// Level-order approach that processes entire levels
/// Time: O(N)
/// Space: O(W)
/// </summary>
if (root == null) {
return null;
}
Queue<TreeNode> queue = new Queue<TreeNode>();
queue.Enqueue(root);
while (queue.Count > 0) {
int levelSize = queue.Count;
// Process entire level
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.Dequeue();
// Swap children
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// Add next level nodes
if (node.left != null) {
queue.Enqueue(node.left);
}
if (node.right != null) {
queue.Enqueue(node.right);
}
}
}
return root;
}
Key Insights
- Simple Operation: Inverting only requires swapping left and right children at each node
- Any Traversal Works: Preorder, postorder, level-order all work equally well
- In-Place Operation: No additional nodes need to be created
- Recursive vs Iterative: Both approaches have same time complexity but different space characteristics
Edge Cases
- Empty tree: Return null
- Single node: Return the node unchanged
- Only left children: Becomes only right children
- Only right children: Becomes only left children
- Balanced tree: Remains balanced after inversion
Common Mistakes
- Creating new nodes: Inverting should modify existing tree, not create new one
- Forgetting base case: Not handling null nodes in recursion
- Wrong swap logic: Not properly swapping the children
- Stack overflow: Deep recursion on very unbalanced trees
- Modifying during traversal: Incorrectly handling node references after swapping
Follow-up Questions
- Double inversion: What happens if you invert a tree twice?
- Check if inverted: Given two trees, check if one is inversion of other
- Partial inversion: Invert only nodes at even/odd levels
- Mirror check: Check if a tree is symmetric (mirror of itself)
- Invert subtree: Invert only a specific subtree