Subtree of a Binary Tree
Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and false otherwise.
A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node’s descendants. The tree tree could also be considered as a subtree of itself.
Example 1:
Input: root = [1,2,3,4,5], subRoot = [2,4,5]
Output: true
Example 2:
Input: root = [1,2,3,4,5,null,null,6], subRoot = [2,4,5]
Output: false
Constraints:
0 <= The number of nodes in both trees <= 100.
-100 <= root.val, subRoot.val <= 100
Solution
As an EASY level problem, the answer should quite brute. We just need to match the nodes between whole tree and subtree one by one in one DFS. The time complexity is O(∣T∣×∣Tsub∣)O(|T|\times|T_{sub}|)O(∣T∣×∣Tsub∣), because at each node of main tree, we will try to match it will the subtree.
However, a more efficient solution which may be HARD level is Tree Traversal + KMP. The subtree’s traversal must be a substring of traversal of main tree.
Code
Brute force, remember to judge whether node is empty.
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
def check(main_node, sub_node):
if main_node is None and sub_node is None:
return True
if main_node is None or sub_node is None:
return False
if main_node.val == sub_node.val:
return check(main_node.left, sub_node.left) and check(main_node.right, sub_node.right)
return False
def dfs(node):
if check(node, subRoot):
return True
if node is None:
return False
return dfs(node.left) or dfs(node.right)
return dfs(root)
Tree Traversal + KMP, remember to add None to the traversal sequence
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
mainstr = []
self.traversal(root, mainstr)
substr = []
self.traversal(subRoot, substr)
print(mainstr)
print(substr)
nxt = [0]*len(substr)
prefix = 0
for suffix in range(1, len(substr)):
while prefix > 0 and substr[prefix] != substr[suffix]:
prefix = nxt[prefix-1]
if substr[prefix] == substr[suffix]:
prefix += 1
nxt[suffix] = prefix
j = 0
for i in range(len(mainstr)):
while j > 0 and substr[j] != mainstr[i]:
j = nxt[j-1]
if substr[j] == mainstr[i]:
j += 1
if j == len(substr):
return True
return False
def traversal(self, node, string):
if node is None:
string.append(None)
return
string.append(node.val)
self.traversal(node.left, string)
self.traversal(node.right, string)
return