树的子结构

解题思路:

  1. 若树 B 是树 A 的子结构,则子结构的根节点可能为树 A 的任意一个节点,因此,判断树 B 是否是树 A 的子结构,需完成以下两步工作:先序遍历树 A 中的每个节点 nA(对应函数 isSubStructure(A, B));再判断树 A 中 以 nA 为根节点的子树是否包含树 B(对应函数 dfs(A, B));

  2. 算法流程:

    • dfs(A, B) 函数:
      • 终止条件:
        • 当节点 B 为空:说明树 B 已匹配完成,因此返回 true;
        • 当节点 A 为空:说明已经越过树 A 叶子节点,即匹配失败,返回 false;
        • 当节点 A 和 B 的值不同:说明匹配失败,返回 false;
      • 返回值:
        • 判断 A 和 B 的左子节点是否相等,即 recur(A.left, B.left) ;
        • 判断 A 和 B 的右子节点是否相等,即 recur(A.right, B.right) ;
    • isSubStructure(A, B) 函数:
      • 特例处理: 当树 A 为空或树 B 为空时,直接返回 false;
      • 返回值: 若树 B 是树 A 的子结构,则必满足以下三种情况之一,因此用或 || 连接;
        • 以节点 A 为根节点的子树包含树 B,对应 dfs(A, B);
        • 树 B 是树 A 左子树的子结构,对应 isSubStructure(A.left, B);
        • 树 B 是树 A 右子树的子结构,对应 isSubStructure(A.right, B);

复杂度:

  1. 时间复杂度: O(MN);其中 M、N 分别为树 A 和树 B 的节点数量;先序遍历树 A 占用 O(M),每次调用 dfs(A, B) 判断占用 O(N);

  2. 空间复杂度: O(M);当树 A 和树 B 都退化为链表时,递归调用深度最大;当 M≤N 时,遍历树 A 与递归判断的总递归深度为 M ;当 M>N 时,最差情况为遍历至树 A 叶子节点,此时总递归深度为 M;

代码实现:

function isSubStructure(A: TreeNode | null, B: TreeNode | null): boolean {
    if (A === null || B === null) return false;

    function dfs(A, B) {
        if (B == null) return true;
        if (A == null) return false;
        return A.val === B.val && dfs(A.left, B.left) && dfs(A.right, B.right);
    }

    return dfs(A, B) || isSubStructure(A.left, B) || isSubStructure(A.right, B);
};
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 树的子结构
  2. 2. 解题思路:
  3. 3. 复杂度:
  4. 4. 代码实现: