Mirror a Binary Tree in DSA Rust - Time & Space Complexity
We want to understand how long it takes to flip a binary tree so its left and right children swap places.
How does the time needed grow as the tree gets bigger?
Analyze the time complexity of the following code snippet.
fn mirror_tree(node: &mut Option>) {
if let Some(n) = node.as_mut() {
mirror_tree(&mut n.left);
mirror_tree(&mut n.right);
std::mem::swap(&mut n.left, &mut n.right);
}
}
This code flips the tree by swapping left and right children for every node recursively.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls visiting each node once.
- How many times: Once per node in the tree.
Each node is visited once to swap its children, so the work grows directly with the number of nodes.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 swaps and recursive calls |
| 100 | About 100 swaps and recursive calls |
| 1000 | About 1000 swaps and recursive calls |
Pattern observation: The time grows linearly as the tree size increases.
Time Complexity: O(n)
This means the time to mirror the tree grows in direct proportion to the number of nodes.
[X] Wrong: "The time depends on the height of the tree only."
[OK] Correct: The function visits every node, not just along one path, so the total nodes matter more than height alone.
Understanding this helps you reason about recursive tree problems and shows you can analyze how recursion scales with input size.
"What if we changed the code to use iteration with a stack instead of recursion? How would the time complexity change?"
Practice
Solution
Step 1: Understand the mirror operation
Mirroring a binary tree means swapping the left and right children of every node in the tree.Step 2: Effect on the tree structure
This operation creates a tree that is a mirror image of the original, flipping it horizontally.Final Answer:
Swap the left and right children of every node -> Option AQuick Check:
Mirror = Swap children [OK]
- Thinking mirror means deleting nodes
- Confusing mirror with sorting nodes
- Assuming mirror changes node values
Solution
Step 1: Understand Rust ownership for swapping
In Rust, to swap children, we must take ownership usingtake()to avoid borrowing issues.Step 2: Analyze the code snippets
let temp = node.left.take(); node.left = node.right.take(); node.right = temp; usestake()to temporarily hold left child, then swaps left and right correctly. node.left = node.right; node.right = node.left; incorrectly assigns right to left and then left to right without temp, causing both to be same.Final Answer:
let temp = node.left.take(); node.left = node.right.take(); node.right = temp; -> Option AQuick Check:
Usetake()to swap safely [OK]
take() to swap children safely in Rust [OK]- Assigning children without temporary variable
- Not using
take()causing borrow errors - Setting children to None accidentally
struct Node {
val: i32,
left: Option,
right: Option,
}
fn mirror(node: &mut Option) {
if let Some(n) = node {
mirror(&mut n.left);
mirror(&mut n.right);
let temp = n.left.take();
n.left = n.right.take();
n.right = temp;
}
}
// Tree before mirror:
// 1
// / \
// 2 3
// / \
// 4 5
// In-order traversal after mirror?Solution
Step 1: Understand the original tree and mirror effect
Original tree in-order: left, root, right = [4, 2, 1, 3, 5]. Mirror swaps left and right children at every node.Step 2: Perform mirror and in-order traversal
After mirror, tree structure:
1
/ \ 3 2 / \ 5 4 In-order traversal now: left(3 subtree), root(1), right(2 subtree) = [5, 3, 1, 4, 2]Final Answer:
[5, 3, 1, 4, 2] -> Option DQuick Check:
Mirror flips children, in-order changes accordingly [OK]
- Not swapping children before traversal
- Confusing pre-order with in-order traversal
- Assuming in-order stays same after mirror
fn mirror(node: &mut Option) {
if let Some(n) = node {
mirror(&mut n.left);
mirror(&mut n.right);
n.left = n.right.take();
n.right = n.left.take();
}
}Solution
Step 1: Analyze the swapping lines
The code assignsn.left = n.right.take()first, which moves right child to left and sets right to None. Thenn.right = n.left.take()tries to take from left, which is now the old right child, but after first take, left is already moved, so it becomes None.Step 2: Identify the bug
Both children end up None because the second take is from a moved value. Correct approach is to use a temporary variable to hold one child before swapping.Final Answer:
Swapping children incorrectly causes both to be None -> Option CQuick Check:
Swap needs temp variable to avoid losing nodes [OK]
- Swapping without temp causes data loss
- Ignoring ownership rules in Rust
- Assuming recursion order fixes swap
Solution
Step 1: Understand the correct order of operations
Mirroring must be done first to change the tree structure. Then level order traversal prints nodes level by level using a queue.Step 2: Analyze options
First mirror the tree recursively, then use a queue to print nodes level by level correctly mirrors recursively first, then then uses a queue for level order. Print level order first, then mirror the tree recursively prints before mirror, so output is original. Mirror the tree by swapping values only, then print in-order traversal swaps values only, not structure. Use recursion to print level order while mirroring simultaneously tries recursion for level order which is not straightforward.Final Answer:
First mirror the tree recursively, then use a queue to print nodes level by level -> Option BQuick Check:
Mirror first, then level order with queue [OK]
- Printing before mirroring
- Trying to print level order recursively
- Swapping values instead of nodes
Ready to prove it?
Pass the test and this pattern moves unknown
