Same Tree

Patrick Leaton
Problem Description

Given two binary trees, 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.

Example 1:

Input:     1         1
          / \       / \
         2   3     2   3

        [1,2,3],   [1,2,3]

Output: true

Example 2:

Input:     1         1
          /           \
         2             2

        [1,2],     [1,null,2]

Output: false

Example 3:

Input:     1         1
          / \       / \
         2   1     1   2

        [1,2,1],   [1,1,2]

Output: false

 

The description was taken from https://leetcode.com/problems/same-tree/.

Problem Solution

#Recursive
#O(N) Time, O(log(N)) Space for Balanced, O(N) for Unbalanced Tree
class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if p is None and q is None:
            return True
        if p is None or q is None:
            return False
        if p.val != q.val:
            return False
        return self.isSameTree(p.left, q.left) and \
               self.isSameTree(p.right, q.right)
 
#Iterative
#O(N) Time, O(log(N)) Space for Balanced, O(N) for Unbalanced Tree
class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        stack = [(p,q)]
        while stack :
            x,y = stack.pop()
            if x is None and y is None:
                continue
            if x is None or y is None:
                return False
            if x.val != y.val:
                return False
            else:
                stack.append((x.left,y.left))
                stack.append((x.right,y.right))
        return True

 

Problem Explanation


Recursive Solution

If we are considering two trees to be the same, we would need to have in mind what would make them different.  These two things would be different heights and different values.

Different values are straightforward, if one root is five and the other is four then the trees are different.

Different heights from the bottom is the other invalidation.  If one tree has a subtree with a child node and the other tree doesn't, then that means that the first subtree's child node has a height of one while the other has a height of zero, making them different.

We can solve this problem by checking for mismatched values in the tree roots, and then recursing the isSameTree function on the left and right children until we reach null nodes.


If both nodes are none, they still match so we will return true.

        if p is None and q is None:
            return True

 

If only one of the nodes is none, they don't match so we will return false.

        if p is None or q is None:
            return False

 

If the values of the nodes aren't equal, they don't match so we will return false.

        if p.val != q.val:
            return False

 

If we have checked the values of the nodes and they are the same, we will do the same thing on the left and right children.

        return self.isSameTree(p.left, q.left) and \
               self.isSameTree(p.right, q.right)

 

If all recursive calls have returned true, the trees are the same.



Iterative Solution

The only difference we have to make here is swapping out the call stack for a loop and iterative stack.  This is typically how simple it is to convert a preorder or inorder recursive traversal to an iterative one.

We can solve this problem by checking for mismatched values in the tree roots by pushing them into a stack, and if the nodes match up then we will push the node's children onto the stack and continue.


We will start by initializing a stack and pushing both roots onto it.

        stack = [(p,q)]

 

Then, we will create a loop that will run while the stack still has nodes.

        while stack :

 

During each iteration, we will pop two nodes off of the stack and set two variables, x and y to these nodes.

            x,y = stack.pop()

 

If both nodes are none, they still match so we will continue.

            if x is None and y is None:
                continue

 

If only one of the nodes is none, they don't match so we will return false.

            if x is None or y is None:
                return False

 

If the values of the nodes aren't equal, they don't match so we will return false.

            if x.val != y.val:
                return False

 

Otherwise, if both node values are equal then we will push both of the nodes' children onto the stack and do the same thing.

                stack.append((x.left,y.left))
                stack.append((x.right,y.right))

 

If we get an empty stack, then that means all of the nodes have the same order and values and the trees are the same so we will return true.

        return True