Since I noticed my weakness in recursion and tree problems, I decided to go back to the basics of binary search trees to build up my skills and confidence. One thing I realized is that a solution for one problem can often be a method for solving another.
LeetCode 100: Same Tree
This is a fundamental question that checks whether two given trees are the same.
Once again, the solution requires recursion, and despite my efforts, I had to refer to the answer after an hour of trying. Yes, I can write real-world programs, yet I still struggle with an easy LeetCode problem. The answer was actually quite straightforward, and I probably overcomplicated things:
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        if not p and not q: # both None
            return True
        if not p or not q: # one is None and the other is not
            return False
        if p.val == q.val:
            return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
        
        return False
      Breaking It Down
- If both nodes are None: They are the same.
 - If one is None and the other is not: They are different.
 - If both exist and have the same value: Recursively check their left and right children.
 - Otherwise: They must be different, so return False.
 
LeetCode 101: Symmetric Tree
The main difference here is that instead of checking whether two trees are identical, we check whether a tree is symmetrical.
class Solution:
    def isMirror(self, left, right):
        if not left and not right:
            return True
        if not left or not right:
            return False
        
        if left.val == right.val:
            return self.isMirror(left.left, right.right) and self.isMirror(left.right, right.left)
        return False
        
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        return self.isMirror(root.left, root.right)
      Notice the similarities? The only difference is how we pass the next nodes in a mirrored fashion to check for symmetry.
LeetCode 572: Subtree of Another Tree
This problem is another variation of the "Same Tree" problem, except we need to check if one tree is a subtree of another.
class Solution:
    def isSameTree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
        if not root and not subRoot:
            return True
        if not root or not subRoot:
            return False
        if root.val == subRoot.val:
            return self.isSameTree(root.left, subRoot.left) and self.isSameTree(root.right, subRoot.right)
        return False
    def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
        if not root:
            return False
        if not subRoot:
            return True
        if self.isSameTree(root, subRoot):
            return True
        return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)
      
        Here, we reuse the isSameTree method and apply it to check
        whether the root itself is a subtree. If not, we recursively check its
        left and right branches.
      
Final Thoughts
All three of these problems are categorized as LeetCode "Easy," and I would say that's fair. It’s really about recognizing how we can modify a simple base algorithm to fit different conditions. My biggest challenge seems to be overthinking, especially with easy problems.
But hey, practice makes perfect, right? I’ll keep at it and hopefully improve my skills. Until next time!