🧠
Brute Force (Pure Recursion)
💡 Starting with a simple recursive check helps understand the problem deeply by directly comparing mirrored nodes without any optimization.
Intuition
Check if the left subtree and right subtree are mirror images by recursively comparing their nodes in a mirrored fashion.
Algorithm
- If the root is null, return true (empty tree is symmetric).
- Define a helper function that takes two nodes and checks if they are mirrors.
- In the helper, if both nodes are null, return true.
- If one is null and the other is not, return false.
- Check if the current nodes have the same value and recursively check the left child of one with the right child of the other and vice versa.
- Return the result of the helper function called on root's left and right children.
💡 The challenge is to realize that symmetry means comparing opposite children recursively, not just the same side.
from typing import Optional
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def isSymmetric(root: Optional[TreeNode]) -> bool:
def isMirror(t1: Optional[TreeNode], t2: Optional[TreeNode]) -> bool:
if not t1 and not t2:
return True
if not t1 or not t2:
return False
return (t1.val == t2.val) and isMirror(t1.left, t2.right) and isMirror(t1.right, t2.left)
return isMirror(root.left, root.right) if root else True
# Example usage:
# root = TreeNode(1, TreeNode(2), TreeNode(2))
# print(isSymmetric(root)) # Output: True
Line Notes
def isMirror(t1: Optional[TreeNode], t2: Optional[TreeNode]) -> bool:Defines the recursive helper to compare two nodes for mirror symmetry
if not t1 and not t2:Base case: both nodes are null means symmetric at this branch
if not t1 or not t2:If one node is null and the other isn't, symmetry breaks here
return (t1.val == t2.val) and isMirror(t1.left, t2.right) and isMirror(t1.right, t2.left)Check current node values and recurse on opposite children to verify mirror
public class Solution {
public static class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
public boolean isSymmetric(TreeNode root) {
if (root == null) return true;
return isMirror(root.left, root.right);
}
private boolean isMirror(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return true;
if (t1 == null || t2 == null) return false;
return (t1.val == t2.val) && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left);
}
// Example usage:
// public static void main(String[] args) {
// TreeNode root = new TreeNode(1);
// root.left = new TreeNode(2);
// root.right = new TreeNode(2);
// System.out.println(new Solution().isSymmetric(root)); // true
// }
}
Line Notes
public boolean isSymmetric(TreeNode root) {Entry point to check symmetry starting from root
if (root == null) return true;Empty tree is symmetric by definition
return isMirror(root.left, root.right);Start recursive mirror check on left and right subtrees
return (t1.val == t2.val) && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left);Check current nodes and recurse on mirrored children
#include <iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
return isMirror(root->left, root->right);
}
private:
bool isMirror(TreeNode* t1, TreeNode* t2) {
if (!t1 && !t2) return true;
if (!t1 || !t2) return false;
return (t1->val == t2->val) && isMirror(t1->left, t2->right) && isMirror(t1->right, t2->left);
}
};
// Example usage:
// int main() {
// TreeNode* root = new TreeNode(1);
// root->left = new TreeNode(2);
// root->right = new TreeNode(2);
// Solution sol;
// cout << sol.isSymmetric(root) << endl; // Output: 1 (true)
// return 0;
// }
Line Notes
bool isSymmetric(TreeNode* root) {Public method to start symmetry check
if (!root) return true;Empty tree is symmetric
return isMirror(root->left, root->right);Begin recursive mirror comparison
return (t1->val == t2->val) && isMirror(t1->left, t2->right) && isMirror(t1->right, t2->left);Check node values and recurse on mirrored children
function TreeNode(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
var isSymmetric = function(root) {
if (!root) return true;
function isMirror(t1, t2) {
if (!t1 && !t2) return true;
if (!t1 || !t2) return false;
return (t1.val === t2.val) && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left);
}
return isMirror(root.left, root.right);
};
// Example usage:
// const root = new TreeNode(1, new TreeNode(2), new TreeNode(2));
// console.log(isSymmetric(root)); // true
Line Notes
var isSymmetric = function(root) {Main function to check if tree is symmetric
if (!root) return true;Empty tree is symmetric by default
function isMirror(t1, t2) {Helper function to recursively check mirror symmetry
return (t1.val === t2.val) && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left);Compare current nodes and recurse on opposite children
Each node is visited once in the recursion. The recursion stack can go as deep as the tree height h.
💡 For a tree with 1000 nodes and height 10, this means roughly 1000 operations and stack depth of 10.
Interview Verdict: Accepted
This approach is efficient and accepted for the problem constraints, making it a solid baseline solution.