101. Symmetric Tree - Explanation
Description
Return true if the binary tree is symmetric about its root, or false otherwise. Mirrored positions must either both be absent or contain equal values: a left child on one side corresponds to a right child on the other.
Examples encode trees in level order. After the root, each present node contributes its left and right child entries in queue order; null marks a missing child, and trailing missing entries may be omitted.
Example 1:
Input: root = [9,4,4,null,7,7,null]
Output: trueExplanation: The two children both have value 4. The left child has a right child with value 7, mirrored by the right child's left child with value 7. The outer child positions are both empty.
Example 2:
Input: root = [9,4,4,null,7,null,7]
Output: falseExplanation: Both nodes with value 4 have only a right child. These child positions do not mirror one another, even though both grandchildren have value 7, so the tree is not symmetric.
Example 3:
Input: root = [0]
Output: trueExplanation: A single root has no children. Its two sides are both empty, so it is symmetric.
Constraints:
- The tree contains between 1 and 1000 nodes.
-100 <= Node.val <= 100
Follow-up: Can you solve the problem both recursively and iteratively?
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- Binary Tree Structure - Understanding nodes, left/right children, and tree traversal basics
- Recursion - Writing recursive functions that process tree nodes and combine results from subtrees
- DFS/BFS on Trees - Traversing trees iteratively using stacks (DFS) or queues (BFS)
1. Depth First Search
Intuition
A tree is symmetric if its left subtree is a mirror reflection of its right subtree. Two trees are mirrors of each other if their roots have the same value, and the left subtree of one is a mirror of the right subtree of the other (and vice versa). We can check this recursively by comparing pairs of nodes that should be mirror images of each other.
Algorithm
- Define a recursive helper that takes two nodes: one from the left subtree and one from the right subtree.
- If both nodes are
null, they are mirrors (returntrue). - If only one is
null, or their values differ, they are not mirrors (returnfalse). - Recursively check:
- The left child of the left node against the right child of the right node.
- The right child of the left node against the left child of the right node.
- Return
trueonly if both recursive checks pass. - Start by comparing the root's left and right children.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
def dfs(left, right):
if not left and not right:
return True
if not left or not right:
return False
return (
left.val == right.val and
dfs(left.left, right.right) and
dfs(left.right, right.left)
)
return dfs(root.left, root.right)Time & Space Complexity
- Time complexity:
- Space complexity: for recursion stack.
2. Iterative DFS
Intuition
The recursive solution can be converted to an iterative one using a stack. Instead of implicit recursive calls, we explicitly push pairs of nodes onto a stack. Each pair represents two nodes that should be mirror images. By processing pairs from the stack, we maintain the same comparison logic without recursion.
Algorithm
- Push the initial pair
(root.left, root.right)onto the stack. - While the stack is not empty:
- Pop a pair of nodes.
- If both are
null, continue to the next pair. - If only one is
nullor their values differ, returnfalse. - Push two new pairs:
(left.left, right.right)and(left.right, right.left).
- If all pairs pass, return
true.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
stack = [(root.left, root.right)]
while stack:
left, right = stack.pop()
if not left and not right:
continue
if not left or not right or left.val != right.val:
return False
stack.append((left.left, right.right))
stack.append((left.right, right.left))
return TrueTime & Space Complexity
- Time complexity:
- Space complexity:
3. Breadth First Search
Intuition
BFS processes nodes level by level using a queue. For symmetry checking, we enqueue pairs of nodes that should be mirrors. Processing the queue ensures we compare nodes at the same depth before moving deeper. This approach gives a level-by-level validation of the mirror property.
Algorithm
- Initialize a queue with the pair
(root.left, root.right). - While the queue is not empty:
- For each pair in the current level:
- Dequeue a pair.
- If both are
null, continue. - If only one is
nullor values differ, returnfalse. - Enqueue pairs:
(left.left, right.right)and(left.right, right.left).
- For each pair in the current level:
- If all comparisons pass, return
true.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
queue = deque([(root.left, root.right)])
while queue:
for _ in range(len(queue)):
left, right = queue.popleft()
if not left and not right:
continue
if not left or not right or left.val != right.val:
return False
queue.append((left.left, right.right))
queue.append((left.right, right.left))
return TrueTime & Space Complexity
- Time complexity:
- Space complexity:
Common Pitfalls
Comparing Wrong Node Pairs
A frequent mistake is comparing left.left with right.left instead of left.left with right.right. For a mirror reflection, the left child of the left subtree must match the right child of the right subtree, and vice versa.
Forgetting to Handle Null Cases First
When checking symmetry, you must handle the null cases before accessing node values. Checking left.val == right.val when either node is null will cause a null pointer exception. Always check if both are null (return true) or only one is null (return false) before comparing values.
Sign in to join the discussion