Symmetric Tree
EasyGiven the root
of a binary tree, check
whether it is a mirror of itself (i.e., symmetric around its center).
Example
Example 1:
Input: root = [1,2,2,3,4,4,3]
Output: true
Example 2:
Input: root = [1,2,2,null,3,null,3]
Output: false
Explanation
A tree is symmetric if its left and right subtrees are mirror images of each other. We can solve this using recursion by comparing corresponding nodes.
The Mirror Property
Two trees are mirrors of each other if:
- Both roots have the same value
- The left subtree of tree1 equals the right subtree of tree2
- The right subtree of tree1 equals the left subtree of tree2
Approach: Recursive Comparison
We use a helper function that takes two nodes and checks if they are mirrors:
- If both nodes are
null, returntrue - If only one node is
null, returnfalse - Check if values are equal AND recursively compare (left1, right2) AND (right1, left2)
Idea Map
Call isMirror(root.left, root.right)
For each pair (node1, node2):
if both null → true
if one null → false
if values differ → false
Recursively check: isMirror(left1, right2) && isMirror(right1, left2)
Complexity Analysis
Time Complexity
O(n) - We visit each node exactly once, where n is the number of nodes in the tree.
Space Complexity
O(h) - The recursion stack depth equals the height of the tree. In worst case (skewed tree), O(n). Best case (balanced), O(log n).
Code
class TreeNode:
Definition for a binary tree node with val, left, and right attributes.
def __init__(self, val=0, left=None, right=None):
Constructor initializes node with value and optional left/right children.
self.val = val
Store the node's value.
self.left = left
Reference to left child node.
self.right = right
Reference to right child node.
def isSymmetric(root: TreeNode) -> bool:
Main function that checks if the tree is symmetric. Takes the root node and returns a boolean.
if not root:
Edge case: empty tree is considered symmetric.
return True
Return True for empty tree (base case).
return isMirror(root.left, root.right)
Start the mirror check from the left and right children of root.
def isMirror(t1: TreeNode, t2: TreeNode) -> bool:
Helper function that recursively checks if two trees are mirrors of each other.
if not t1 and not t2:
If both nodes are null, they are mirrors (base case).
return True
Return True when both subtrees are empty.
if not t1 or not t2:
If only one node is null, they cannot be mirrors.
return False
Return False when structures don't match.
return (t1.val == t2.val
Check if current nodes have the same value.
and isMirror(t1.left, t2.right)
Recursively check: left child of t1 vs right child of t2 (cross comparison).
and isMirror(t1.right, t2.left))
Recursively check: right child of t1 vs left child of t2 (cross comparison).
public class TreeNode {
Definition for a binary tree node.
int val;
Node's integer value.
TreeNode left;
Reference to left child.
TreeNode right;
Reference to right child.
TreeNode() {}
Default constructor.
TreeNode(int val) { this.val = val; }
Constructor with value only.
TreeNode(int val, TreeNode left, TreeNode right) {
Full constructor with value and children.
this.val = val;
Assign value.
this.left = left;
Assign left child.
this.right = right;
Assign right child.
}
End constructor.
}
End TreeNode class.
public boolean isSymmetric(TreeNode root) {
Main method to check if tree is symmetric.
return root == null || isMirror(root.left, root.right);
Return true if root is null, otherwise check if left and right subtrees are mirrors.
}
End isSymmetric method.
private boolean isMirror(TreeNode t1, TreeNode t2) {
Helper method to check if two trees are mirrors.
if (t1 == null && t2 == null) return true;
Both null means they are mirrors (base case).
if (t1 == null || t2 == null) return false;
Only one null means not mirrors.
return (t1.val == t2.val)
Check if values are equal.
&& isMirror(t1.left, t2.right)
Cross compare: left of t1 with right of t2.
&& isMirror(t1.right, t2.left);
Cross compare: right of t1 with left of t2.
}
End isMirror method.
struct TreeNode {
Definition for a binary tree node struct.
int val;
Node's integer value.
TreeNode *left;
Pointer to left child.
TreeNode *right;
Pointer to right child.
TreeNode() : val(0), left(nullptr), right(nullptr) {}
Default constructor using initializer list.
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
Constructor with value only.
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
Full constructor with value and children.
};
End TreeNode struct.
bool isSymmetric(TreeNode* root) {
Main function to check if tree is symmetric.
return !root || isMirror(root->left, root->right);
Return true if root is null, otherwise check mirror property.
}
End isSymmetric function.
bool isMirror(TreeNode* t1, TreeNode* t2) {
Helper function to check if two trees are mirrors.
if (!t1 && !t2) return true;
Both null means they are mirrors.
if (!t1 || !t2) return false;
Only one null means not mirrors.
return (t1->val == t2->val)
Check if values are equal using arrow operator.
&& isMirror(t1->left, t2->right)
Cross compare: left of t1 with right of t2.
&& isMirror(t1->right, t2->left);
Cross compare: right of t1 with left of t2.
}
End isMirror function.
Edge Cases & Common Mistakes
Empty tree
An empty tree (null root) is considered symmetric. Always handle this edge case at the beginning.
Single node tree
A tree with only a root node (no children) is symmetric by definition.
Cross comparison
Remember to compare left child of subtree1 with right child of subtree2 (mirror property), not left with left.
Iterative approach
You can also solve this iteratively using a queue (BFS-style), pushing pairs of nodes to compare.
Related Problems
Understanding Tree Traversals
Tree symmetry relies on understanding how to traverse and compare tree structures. Master tree traversals to solve a wide variety of tree problems efficiently.
Learn more about tree traversals →Disclaimer: This problem is for educational purposes. Practice the 'Symmetric Tree' problem on LeetCode.