Skip to content

子结构判断

约 790 字大约 3 分钟

2025-02-28

LCR 143. 子结构判断

给定两棵二叉树 tree1tree2,判断 tree2 是否与以 tree1 的某个节点为根的子树具有 相同的结构和节点值

注意,空树 不会与以 tree1 的某个节点为根的子树具有 相同的结构和节点值

示例 1:

img.png

输入:tree1 = [1,7,5], tree2 = [6,1]
输出:false
解释:tree2 与 tree1 的一个子树没有相同的结构和节点值。

示例 2:

输入:tree1 = [3,6,7,1,8], tree2 = [6,1]
输出:true
解释:tree2 与 tree1 的一个子树拥有相同的结构和节点值。即 6 - > 1。

提示:

0 <= 节点个数 <= 10000

递归-自顶向下

class Solution {
    String target;
    boolean found = false;

    // 这个函数用「遍历」的思维模式理解,遍历二叉树 A 的所有节点
    public boolean isSubStructure(TreeNode A, TreeNode B) {
        // 题目说空树不会与以 `tree1` 的某个节点为根的子树具有相同的结构和节点值。
        if (A == null || B == null) {
            return false;
        }
        
        // 对于树 A 中的一个节点:
        // 1. A 可以作为根节点尝试去匹配树 B
        if (compareTree(A, B)) {
            return true;
        }
        // 2. 如果 A.val != B.val,就不要去匹配树 B 了。注意,固定用B与A的子树比较。
        // 注意最坏情况是遍历A的所有节点,而不是每次一定遍历一半!所以时间复杂度不是对数。
        return isSubStructure(A.left, B) || isSubStructure(A.right, B);
    }

    // 这个函数用「分解问题」的思路理解
    // 定义:输入两个根节点,返回从 rootA 开始是否可以完全匹配 rootB 树上的所有节点
    boolean compareTree(TreeNode rootA, TreeNode rootB) {
        // 结束条件:rootB为空,rootA随便。注意这里的rootB==null指的是前进到B的空节点,不是指一开始rootB就是空,
        // isSubStructure中有判空,所以一开始rootB一定不为空。
        if (rootB == null) {
            return true;
        }
        // 结束条件:rootA为空且rootB不为空
        if (rootA == null) {
            return false;
        }
        // 结束条件:rootA和rootB都不为空且不相等
        if (rootA.val != rootB.val) {
            return false;
        }

        // rootA 的值和 rootB 的值匹配完成,去匹配子树的节点
        return compareTree(rootA.left, rootB.left) && compareTree(rootA.right, rootB.right);
    }
}
  • 时间复杂度 O(MN):其中 M,N 分别为树 A 和 树 B 的节点数量;先序遍历树 A 占用 O(M),每次调用 compareTree(A, B) 判断占用 O(N) 。
  • 空间复杂度 O(M):当树 A 和树 B 都退化为链表时,递归调用深度最大。当 M≤N 时,遍历树 A 与递归判断的总递归深度为 M ; 当 M>N 时,最差情况为遍历至树 A 的叶节点,此时总递归深度为 M。

注意就算isSubStructure每次都执行一次compareTree,递归栈也是M,不是M^2,因为compareTree返回后递归栈会被销毁,下次运行的时候再创建。

能不能用备忘录优化?可以,但比较麻烦,因为正常来说备忘录是哈希表,哈希表的键是节点的值,值是true或false,但是二叉树中可能有重复的节点值。