DSAPrep
EasyTrees

Subtree of Another 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 = [3,4,5,1,2], subRoot = [4,1,2]
Output: true

Example 2

Input: root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
Output: false

Constraints

  • The number of nodes in the root tree is in the range [1, 2000].
  • The number of nodes in the subRoot tree is in the range [1, 1000].
  • -10^4 <= Node.val <= 10^4
View original on LeetCode ↗

“Is subRoot a subtree of root?” reduces to “does any node in root start an identical tree to subRoot?” — that reuses the exact same-tree check from the Same Tree problem, just run at every candidate node.

Brute Force (same-tree check at every node)

Time O(m * n)Space O(h)

Walk root with DFS. At each node, run a full isSameTree comparison against subRoot. If any node matches, subRoot is a subtree.

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: TreeNode | None, subRoot: TreeNode | None) -> bool:
if root is None:
return False
if self.isSameTree(root, subRoot):
return True
return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)
def isSameTree(self, p: TreeNode | None, q: TreeNode | None) -> 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)

Tracing root = [3,4,5,1,2], subRoot = [4,1,2]isSameTree is tried at each node of root until one matches:

3
4
5
1
2
1 / 2
seenresultdiscarded

isSameTree(root=3, subRoot=4): values 3 != 4, mismatch. Not a match at this node -- recurse into children instead.

Complexity: in the worst case, isSameTree (O(n), the size of subRoot) is attempted at every one of the m nodes of rootO(m * n) time. Recursion depth is the height of rootO(h) space.

Serialize + Substring Search

OptimalTime O(m + n)Space O(m + n)

Serialize both trees to strings that uniquely encode structure (using explicit null markers and separators so no value can be mistaken for a different shape), then subRoot is a subtree of root exactly when its serialization is a substring of root’s. Python’s in operator uses an efficient substring search under the hood, giving a near-linear check.

class Solution:
def isSubtree(self, root: TreeNode | None, subRoot: TreeNode | None) -> bool:
def serialize(node: TreeNode | None) -> str:
if node is None:
return ",#"
return f",{node.val}{serialize(node.left)}{serialize(node.right)}"
return serialize(subRoot) in serialize(root)

Why prefer this: each tree is serialized once in O(m) / O(n) time, and the substring search is near-linear in practice → O(m + n) time overall versus the brute force’s O(m * n). The , separator and # null-marker prevent false matches like value 12 accidentally matching inside value 312. Space grows to hold both serialized strings → O(m + n).