GoCalf Calf 的自留地 · 昙花一现

572. Subtree of Another Tree

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:

case1
case1

Input: root = [3,4,5,1,2], subRoot = [4,1,2]
Output: true

Example 2:

case2
case2

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

Test Cases

python
# 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下载完整源码
py
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 的子树,先判断 root 跟 subRoot 是否相等,不相等的话再递归判定 subRoot 是不是 root.left 或 root.right 的子树。同样可以用栈替代递归,对 root 做 NLR 遍历,遍历到任何一个节点时,判断以该节点为根的子树是否跟 subRoot 相等。

设 root 和 subRoot 的节点数分别是 n 和 m,则时间复杂度为 O(n * m)。

Code

py
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

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

评论需要 JavaScript。