Problem

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.

https://leetcode.com/problems/subtree-of-another-tree/

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 <= root.val <= 10^4
  • -10^4 <= subRoot.val <= 10^4

Test Cases

1
2
3
4
5
6
7
8
# 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:
solution_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pytest

from solution import Solution
from utils import build_tree, TreeNode

null = None


@pytest.mark.parametrize('root, subRoot, expected', [
([3,4,5,1,2], [4,1,2], True),
([3,4,5,1,2,null,null,null,null,0], [4,1,2], False),
])
class Test:
def test_solution(self, root, subRoot, expected):
sol = Solution()
root = build_tree(root)
subRoot = build_tree(subRoot)
assert sol.isSubtree(root, subRoot) == expected

Thoughts

先看比较两颗二叉树是否相等。同时按同样的顺序遍历两颗树,只要出现一边有节点另一边是空,或者两边节点的值不同,就不相等。

比如用前序遍历(NLR)。可以用栈替代递归,给两个树各维持一个栈,或者用一个栈但每次把两棵树的节点打包入栈。

要判断 subRoot 是否是 root 的子树,先判断 rootsubRoot 是否相等,不相等的话再递归判定 subRoot 是不是 root.leftroot.right 的子树。同样可以用栈替代递归,对 root 做 NLR 遍历,遍历到任何一个节点时,判断以该节点为根的子树是否跟 subRoot 相等。

rootsubRoot 的节点数分别是 nm,则时间复杂度为 O(n * m)

Code

solution.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from typing import Optional

from utils import TreeNode

# 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:
stack = []
while root or stack:
if root:
if self._is_same(root, subRoot):
return True
stack.append(root)
root = root.left
else:
root = stack.pop().right

return False

def _is_same(self, root1: TreeNode|None, root2: TreeNode|None) -> bool:
stack = []
while root1 or root2 or stack:
if (not not root1) != (not not root2):
return False
elif root1:
if root1.val != root2.val:
return False
stack.append((root1, root2))
root1 = root1.left
root2 = root2.left
elif stack:
root1, root2 = stack.pop()
root1 = root1.right
root2 = root2.right

return True

似乎用栈并不比直接用递归快。