๐ณ Binary Tree Magic: Tree Operations
Imagine you have a family tree made of LEGO blocks. Today, weโll learn how to flip it upside down, check if two trees are twins, hide one tree inside another, build trees from clues, save trees to send to friends, and flatten trees into a single line!
๐ช Invert Binary Tree (The Mirror Trick)
What Does โInvertโ Mean?
Think of looking in a mirror. Your left hand appears on the right side, and your right hand appears on the left. Thatโs exactly what inverting a binary tree does!
Before: After:
4 4
/ \ / \
2 7 โ 7 2
/ \ / \ / \ / \
1 3 6 9 9 6 3 1
The Secret Recipe
At every node, just swap the left and right children!
TreeNode invert(TreeNode root) {
if (root == null) return null;
// Swap left and right
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
// Do the same for children
invert(root.left);
invert(root.right);
return root;
}
Why Is This Famous?
This is one of the most famous coding interview questions. The lesson? Simple problems can stump even experienced programmers!
๐ฏ Same Tree and Symmetric Tree
Same Tree: Are These Twins?
Two trees are the โsameโ if they have identical structure AND identical values.
Tree A: Tree B: Same? โ
1 1
/ \ / \
2 3 2 3
boolean isSameTree(TreeNode p, TreeNode q) {
// Both empty? Same!
if (p == null && q == null) return true;
// One empty, one not? Different!
if (p == null || q == null) return false;
// Different values? Different!
if (p.val != q.val) return false;
// Check both sides
return isSameTree(p.left, q.left) &&
isSameTree(p.right, q.right);
}
Symmetric Tree: Is This a Butterfly?
A tree is symmetric if itโs a mirror of itself. Like a butterfly - the left wing mirrors the right wing!
Symmetric: Not Symmetric:
1 1
/ \ / \
2 2 2 2
/ \ / \ \ \
3 4 4 3 3 3
boolean isSymmetric(TreeNode root) {
if (root == null) return true;
return isMirror(root.left, root.right);
}
boolean isMirror(TreeNode a, TreeNode b) {
if (a == null && b == null) return true;
if (a == null || b == null) return false;
return (a.val == b.val) &&
isMirror(a.left, b.right) &&
isMirror(a.right, b.left);
}
The trick: For symmetry, compare leftโs left with rightโs right, and leftโs right with rightโs left!
๐ Subtree of Another Tree
Whatโs a Subtree?
A subtree is a tree hidden inside another tree. Like finding a small LEGO castle inside a bigger LEGO kingdom!
Main Tree: Subtree:
3 4
/ \ / \
4 5 1 2
/ \
1 2
Is subtree of main tree? โ YES!
The Detective Method
- Search the main tree for a node matching the subtreeโs root
- When found, check if that whole section matches
boolean isSubtree(TreeNode root, TreeNode sub) {
if (root == null) return false;
// Found a match? Check if trees are same
if (isSameTree(root, sub)) return true;
// Keep searching left and right
return isSubtree(root.left, sub) ||
isSubtree(root.right, sub);
}
๐๏ธ Binary Tree Construction from Traversals
The Mystery: Building a Tree from Clues
Imagine you have puzzle pieces. Traversals give you clues about how the tree was explored. With the right clues, you can rebuild the original tree!
The Three Traversals
| Traversal | Order | Example |
|---|---|---|
| Preorder | Root โ Left โ Right | [3,9,20,15,7] |
| Inorder | Left โ Root โ Right | [9,3,15,20,7] |
| Postorder | Left โ Right โ Root | [9,15,7,20,3] |
The Magic Combination
Preorder + Inorder = Complete Tree! Postorder + Inorder = Complete Tree!
Preorder: [3, 9, 20, 15, 7]
Inorder: [9, 3, 15, 20, 7]
Step 1: Preorder[0] = 3 is the root
Step 2: Find 3 in Inorder โ index 1
Step 3: Left subtree has [9], Right has [15,20,7]
Result:
3
/ \
9 20
/ \
15 7
TreeNode build(int[] pre, int[] in) {
return build(pre, 0, pre.length-1,
in, 0, in.length-1);
}
TreeNode build(int[] pre, int ps, int pe,
int[] in, int is, int ie) {
if (ps > pe) return null;
TreeNode root = new TreeNode(pre[ps]);
int rootIdx = findIndex(in, pre[ps]);
int leftSize = rootIdx - is;
root.left = build(pre, ps+1, ps+leftSize,
in, is, rootIdx-1);
root.right = build(pre, ps+leftSize+1, pe,
in, rootIdx+1, ie);
return root;
}
๐ฆ Serialization and Deserialization
What Is Serialization?
Turning a tree into a string you can save or send! Like taking a photo of your LEGO creation so you can rebuild it later.
1
/ \
2 3 โ "1,2,null,null,3,4,5"
/ \
4 5
Why Do We Need This?
- Save a tree to a file
- Send a tree over the internet
- Store a tree in a database
The BFS Approach
// Serialize: Tree โ String
String serialize(TreeNode root) {
if (root == null) return "";
StringBuilder sb = new StringBuilder();
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node == null) {
sb.append("null,");
} else {
sb.append(node.val + ",");
queue.add(node.left);
queue.add(node.right);
}
}
return sb.toString();
}
// Deserialize: String โ Tree
TreeNode deserialize(String data) {
if (data.isEmpty()) return null;
String[] vals = data.split(",");
TreeNode root = new TreeNode(
Integer.parseInt(vals[0]));
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int i = 1;
while (!queue.isEmpty() && i < vals.length) {
TreeNode node = queue.poll();
if (!vals[i].equals("null")) {
node.left = new TreeNode(
Integer.parseInt(vals[i]));
queue.add(node.left);
}
i++;
if (i < vals.length &&
!vals[i].equals("null")) {
node.right = new TreeNode(
Integer.parseInt(vals[i]));
queue.add(node.right);
}
i++;
}
return root;
}
๐ Flatten Binary Tree to Linked List
The Goal
Turn a tree into a single line (linked list) using preorder traversal!
1
/ \
2 5
/ \ \
3 4 6
Becomes:
1 โ 2 โ 3 โ 4 โ 5 โ 6
(all nodes connected via right pointer)
The Clever In-Place Method
We process right-to-left, keeping track of the previous node:
TreeNode prev = null;
void flatten(TreeNode root) {
if (root == null) return;
// Process right first, then left
flatten(root.right);
flatten(root.left);
// Connect current to previous
root.right = prev;
root.left = null;
// Update previous
prev = root;
}
Step-by-Step Visual
Start: Process 6 โ prev = 6
Process 5 โ 5.right = 6, prev = 5
Process 4 โ prev = 4
Process 3 โ 3.right = 4, prev = 3
Process 2 โ 2.right = 3, prev = 2
Process 1 โ 1.right = 2, prev = 1
Result: 1โ2โ3โ4โ5โ6
๐ฏ Summary: Your Tree Operations Toolkit
graph TD A["Tree Operations"] --> B["๐ช Invert"] A --> C["๐ฏ Compare"] A --> D["๐ Subtree"] A --> E["๐๏ธ Construct"] A --> F["๐ฆ Serialize"] A --> G["๐ Flatten"] B --> B1["Swap left & right<br>at every node"] C --> C1["Same Tree: exact match"] C --> C2["Symmetric: mirror match"] D --> D1["Find node, then<br>compare subtrees"] E --> E1["Preorder + Inorder"] E --> E2["Postorder + Inorder"] F --> F1["Tree โ String<br>using BFS"] G --> G1["To linked list<br>via right pointers"]
๐ก Key Insights
| Operation | Time | Space | Key Idea |
|---|---|---|---|
| Invert | O(n) | O(h) | Swap children recursively |
| Same Tree | O(n) | O(h) | Compare node by node |
| Symmetric | O(n) | O(h) | Mirror comparison |
| Subtree | O(mรn) | O(h) | Search + same tree check |
| Construct | O(n) | O(n) | Root from preorder, split with inorder |
| Serialize | O(n) | O(n) | BFS level-by-level |
| Flatten | O(n) | O(h) | Reverse postorder trick |
Remember: Most tree operations use recursion. Trust the recursion - it handles the complexity for you!
๐ Youโve Got This!
These operations might seem tricky at first, but they all follow a pattern:
- Handle the base case (null check)
- Process the current node
- Recursively handle children
Practice each operation a few times, and soon theyโll feel as natural as building with LEGO blocks! ๐งฑ
