medium Mirror Image Trees
Problem Statement
Given two binary trees root and root2, return true if they are mirror images of each other. Otherwise, return false.
Two trees are said to be mirror images if, for every node in one tree, there is a corresponding node in the other tree with a mirrored structure. This means the left subtree of one tree is a mirror reflection of the right subtree of the other tree, and vice versa.
Examples
Example 1
- Input: root1 = [1,2,3,4,null,null,5], root2 = [1,3,2,5,null,null,4]
- Expected Output:
true - Justification: Both trees have the same root, and the left and right subtrees are mirrors of each other.
Example 2
- Input: root1 = [4, 5, 6, null, 7], root2 = [4, 6, 5, null, null, 7]
- Expected Output:
true - Justification: Both trees are a mirror of each other.
Example 3
- Input: root1 = [1, 2, null, 3], root2 = [1, null, 2]
- Expected Output:
false - Justification: The structure of the subtrees differs. The first tree contains node
3but the second tree doesn't.
Try it yourself
Try solving this question here:
✅ Solution Mirror Image Trees
Problem Statement
Given two binary trees root and root2, return true if they are mirror images of each other. Otherwise, return false.
Two trees are said to be mirror images if, for every node in one tree, there is a corresponding node in the other tree with a mirrored structure. This means the left subtree of one tree is a mirror reflection of the right subtree of the other tree, and vice versa.
Examples
Example 1
- Input: root1 = [1,2,3,4,null,null,5], root2 = [1,3,2,5,null,null,4]
- Expected Output:
true - Justification: Both trees have the same root, and the left and right subtrees are mirrors of each other.
Example 2
- Input: root1 = [4, 5, 6, null, 7], root2 = [4, 6, 5, null, null, 7]
- Expected Output:
true - Justification: Both trees are a mirror of each other.
Example 3
- Input: root1 = [1, 2, null, 3], root2 = [1, null, 2]
- Expected Output:
false - Justification: The structure of the subtrees differs. The first tree contains node
3but the second tree doesn't.
Solution
To solve this problem, we will use the Breadth-First Search (BFS) approach, which allows us to traverse both binary trees level by level. We maintain two queues to compare the nodes of both trees at each level in a mirrored manner. We add the left child of the first tree and the right child of the second tree to their respective queues, and vice versa. This way, the algorithm checks for symmetry at every level. If at any point, we find that the node values or their structures differ, we return false. If both queues are empty at the end of traversal, the trees are mirrors, and we return true.
The BFS approach is well-suited for this problem because it ensures that we process all nodes in a controlled manner. By utilizing two queues, we can efficiently compare nodes without recursion, which prevents stack overflow issues for deep trees. This method ensures that both trees are checked for symmetry in a straightforward, iterative manner, making it both effective and space-efficient.
Step-by-Step Algorithm
-
Initial Check:
- If both trees are empty (
root1 == nullandroot2 == null), returntruesince two empty trees are considered mirrors. - If one tree is empty while the other is not, return
false, as they cannot be mirrors.
- If both trees are empty (
-
Queue Initialization:
- Initialize two queues:
queue1andqueue2. - Enqueue the root of the first tree into
queue1and the root of the second tree intoqueue2.
- Initialize two queues:
-
Traversal Loop:
- While both queues are not empty:
- Dequeue the front of both queues (
node1fromqueue1andnode2fromqueue2). - Value Check:
- If the value of
node1is not equal tonode2, returnfalse.
- If the value of
- Left and Right Child Check:
- For the left child of
node1and the right child ofnode2:- If both are not null, enqueue
node1.lefttoqueue1andnode2.righttoqueue2. - If one is null and the other is not, return
false.
- If both are not null, enqueue
- For the right child of
node1and the left child ofnode2:- If both are not null, enqueue
node1.righttoqueue1andnode2.lefttoqueue2. - If one is null and the other is not, return
false.
- If both are not null, enqueue
- For the left child of
- Dequeue the front of both queues (
- While both queues are not empty:
-
Completion:
- After the traversal loop, check if both queues are empty.
- If both are empty, return
true(the trees are mirrors). Otherwise, returnfalse.
Algorithm Walkthrough
Input: root1 = [1,2,3,4,null,null,5], root2 = [1,3,2,5,null,null,4]
-
Initial Check:
- Both
root1androot2are not null, so we proceed.
- Both
-
Queue Initialization:
- Enqueue
root1(value1) intoqueue1. - Enqueue
root2(value1) intoqueue2.
- Enqueue
-
First Iteration:
- Dequeue
queue1→node1 = 1. - Dequeue
queue2→node2 = 1. - Value Check:
node1.val == node2.val(1 == 1), so continue. - Left and Right Child Check:
node1.left = 2andnode2.right = 2: Both are not null, so enqueue2toqueue1and2toqueue2.node1.right = 3andnode2.left = 3: Both are not null, so enqueue3toqueue1and3toqueue2.
- Dequeue
-
Second Iteration:
- Dequeue
queue1→node1 = 2. - Dequeue
queue2→node2 = 2. - Value Check:
node1.val == node2.val(2 == 2), so continue. - Left and Right Child Check:
node1.left = 4andnode2.right = 4: Both are not null, so enqueue4toqueue1and4toqueue2.node1.right = nullandnode2.left = null: Both are null, so continue.
- Dequeue
-
Third Iteration:
- Dequeue
queue1→node1 = 3. - Dequeue
queue2→node2 = 3. - Value Check:
node1.val == node2.val(3 == 3), so continue. - Left and Right Child Check:
node1.left = nullandnode2.right = null: Both are null, so continue.node1.right = 5andnode2.left = 5: Both are not null, so enqueue5toqueue1and5toqueue2.
- Dequeue
-
Fourth Iteration:
- Dequeue
queue1→node1 = 4. - Dequeue
queue2→node2 = 4. - Value Check:
node1.val == node2.val(4 == 4), so continue. - Left and Right Child Check:
node1.left = nullandnode2.right = null: Both are null, so continue.node1.right = nullandnode2.left = null: Both are null, so continue.
- Dequeue
-
Fifth Iteration:
- Dequeue
queue1→node1 = 5. - Dequeue
queue2→node2 = 5. - Value Check:
node1.val == node2.val(5 == 5), so continue. - Left and Right Child Check:
node1.left = nullandnode2.right = null: Both are null, so continue.node1.right = nullandnode2.left = null: Both are null, so continue.
- Dequeue
-
Completion:
- Both
queue1andqueue2are now empty, meaning the trees are mirror images. Returntrue.
- Both
Code
import java.util.LinkedList;
import java.util.Queue;
// class TreeNode {
// int val;
// TreeNode left;
// TreeNode right;
// TreeNode(int val) {
// this.val = val;
// left = null;
// right = null;
// }
// }
public class Solution {
public boolean areMirrors(TreeNode root1, TreeNode root2) {
// If both roots are null, they are mirrors
if (root1 == null && root2 == null) return true;
// If one is null and the other is not, they are not mirrors
if (root1 == null || root2 == null) return false;
Queue<TreeNode> queue1 = new LinkedList<>();
Queue<TreeNode> queue2 = new LinkedList<>();
// Start by adding both roots to their respective queues
queue1.add(root1);
queue2.add(root2);
while (!queue1.isEmpty() && !queue2.isEmpty()) {
// Poll the front of each queue
TreeNode node1 = queue1.poll();
TreeNode node2 = queue2.poll();
// Check if the values are different
if (node1.val != node2.val) return false;
// Add children in mirror order
// Add left child of root1 and right child of root2 to queues
if (node1.left != null && node2.right != null) {
queue1.add(node1.left);
queue2.add(node2.right);
} else if (!(node1.left == null && node2.right == null)) {
return false; // One child is null, the other is not
}
// Add right child of root1 and left child of root2 to queues
if (node1.right != null && node2.left != null) {
queue1.add(node1.right);
queue2.add(node2.left);
} else if (!(node1.right == null && node2.left == null)) {
return false; // One child is null, the other is not
}
}
return queue1.isEmpty() && queue2.isEmpty();
}
public static void main(String[] args) {
// Creating first tree root1 = [1,2,3,4,null,null,5]
TreeNode root1 = new TreeNode(1);
root1.left = new TreeNode(2);
root1.right = new TreeNode(3);
root1.left.left = new TreeNode(4);
root1.right.right = new TreeNode(5);
// Creating second tree root2 = [1,3,2,5,null,null,4]
TreeNode root2 = new TreeNode(1);
root2.left = new TreeNode(3);
root2.right = new TreeNode(2);
root2.left.left = new TreeNode(5);
root2.right.right = new TreeNode(4);
// Create instance of Solution to call areMirrors method
Solution solution = new Solution();
// Test the trees and print the result
boolean result = solution.areMirrors(root1, root2);
System.out.println("Are the two trees mirror images? " + result); // Expected output: true
}
}
Complexity Analysis
Time Complexity
- In the worst-case scenario, both trees will have
nnodes (wherenis the number of nodes in either tree). - During the BFS traversal, every node in both trees is visited exactly once. For each node, we perform constant-time operations (checking if values match, enqueueing children, etc.).
- Hence, the overall time complexity is
, where nis the number of nodes in the trees.
Space Complexity
- The space complexity is determined by the maximum size of the queue. In the worst-case scenario, both trees are balanced, and the queue can hold at most
nodes at a given time (since we are storing nodes of both trees in queues). - Therefore, the space complexity is
.
🤖 Don't fully get this? Learn it with Claude
Stuck on Mirror Image Trees? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Mirror Image Trees** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Mirror Image Trees** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Mirror Image Trees**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Mirror Image Trees**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.