class Solution: def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: """ go thru each node if node is equal to subroot node, do dfs on it """ q = deque([root]) while q: cur = q.popleft() if cur.val == subRoot.val: if self.dfs(cur, subRoot): return True if cur.left: q.append(cur.left) if cur.right: q.append(cur.right) return False def dfs(self, cur1, cur2): if not cur1 and not cur2: return True elif cur1 and cur2 and cur1.val == cur2.val: return self.dfs(cur1.left, cur2.left) and self.dfs(cur1.right, cur2.right) else: return False
My idea was to just iterate using BFS (a stack), and if the current node’s value is the same as the subRoot, then u perform DFS
so BFS + DFS
The DFS part is just checking if they are the same subtree
Time complexity
O(M * N)
O(M) - inner dfs function
checks if 2 trees are identical. in the worst case it must visit every node in subRoot
O(N) - the outer isSubtree function
checks the main tree with a queue. worst case it checks every node
official solution
DFS + DFS
class Solution: def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: """ go thru each node if node is equal to subroot node, do dfs on it """ if not subRoot: # empty trees are subtrees of all trees return True if not root: # means we have a subRoot but no root -> alse! return False if self.dfs(root, subRoot): return True return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot) def dfs(self, cur1, cur2): if not cur1 and not cur2: return True elif cur1 and cur2 and cur1.val == cur2.val: return self.dfs(cur1.left, cur2.left) and self.dfs(cur1.right, cur2.right) else: return False
The two base cases
if not subRoot: return True
checks if subRoot is empty.. that means we can just return True
if not root: return False
it means we havent found any equal subtree and we passed an empty root.left or root.right
then it means that in this root.left or root.right (which is empty) there is no more equal subtree in this path
edge cases
root and subRoot are both None
they are in that specific order because if not:
Then if not root: return False would return False, but the application should actually return True
a null subtree is a subtree of another null subtree