Search code examples
pythonalgorithmdata-structuresbinary-tree

LeetCode Problem same Tree, why does my code fail when input contains "Null"?


I am looking at the LeetCode problem "100. Same Tree":

Given the roots of two binary trees p and q, write a function to check if they are the same or not.

Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.

My code passes some test cases and fails others.

My specific problem is with the test case [1,2] and [1,null,2]. Python uses None not null. When I use my local code editor (visual studio code) it produces the expected output. I know I could implement this in other ways but I don't understand why this solution won't work on LeetCode.

Here is my code:

class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        answer1 = []
        answer2 = []
        self.helperFunction(p, q, answer1, answer2)
        
        for i in range(len(answer1)):
            if answer1[i] != answer2[i]:
                return False   
        return True
    
    
    def helperFunction(self, p, q, answer1, answer2):
        if p != None and q != None:
            self.helperFunction(p.left, q.left, answer1, answer2)
            answer1.append(p.val)
            answer2.append(q.val)
            self.helperFunction(p.right, q.right, answer1, answer2)

Solution

  • Your code assumes that both trees have the same shape. If however one tree has a child where the other doesn't, your code never visits that child, and this will give false positives when the rest of the tree is the same. The mere presence of such a child (that does not exist in the other tree) would be enough indication to abort the process and return False.

    As to the algorithm itself. It is a pity that you do this:

        answer1.append(p.val)
        answer2.append(q.val)
    

    ...when you could actually compare these two values immediately (instead of doing this at the very end). Why not check p.val == q.val and if that is not true, stop looking any further? On the other hand, if they are equal, there is no reason to append those values to lists either. It just means "so far so good", and you can continue...

    Concluding:

    • Return True when at both sides there is no node (None)
    • Return False when on one side you have a node that is not there on the other side
    • Return False when the values of corresponding nodes are different
    • Return True if and only when the recursion also returns True for both children.

    Implemented:

    class Solution:
        def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
            return bool(not p and not q     or
                        p and q and p.val == q.val and self.isSameTree(p.left, q.left) 
                                                   and self.isSameTree(p.right, q.right))