力扣【二叉树专题】👊 572. 另一棵树的子树

273 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 2 天,点击查看活动详情

题目链接

572. 另一棵树的子树

题目描述

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

测试用例

示例 1:

image.png

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

限制

  • root 树上的节点数量范围是 [1, 2000]
  • subRoot 树上的节点数量范围是 [1, 1000]
  • 104<=root.val<=104-10^4 <= root.val <= 10^4
  • 104<=subRoot.val<=104-10^4 <= subRoot.val <= 10^4

题目分析

题目中对相同的判定为,具备同样的节点层次,以及对应位置的节点的值相等

即我们需要在对 root 进行遍历的时候,需要检查每一个节点的值,是否与 subRoot 这棵树的根节点的值相等。

值不等时,继续遍历 root 的子节点

值相等时,定义 root 此时遍历的节点为 n1,我们开始对 n1, subRoot 两棵树同步遍历以及节点的值的比对,当他们的节点的层次不一致或者值不一致时,返回 false 表示此次比对 subRoot 不是 root 的子树;若当前位置的节点的值符合要求时,继续对比他们的左右子节点。考虑到这个比对操作需要全部满足才能返回 true,可以使用 && 进行短接。

比较校验的函数如下:

function check(n1, n2) {
    if (n1 == null && n2 == null) return true;
    if (n1 == null || n2 == null || n1.val != n2.val) return false;
    return check(n1.left, n2.left) && check(n1.right, n2.right);
}

代码实现

分析完成后,我们需要定义一个对 root 遍历的函数,以及比较两颗树是否相同的函数

在遍历和比较的时候,穿插一个 flag 标记 root 中是否存在目标子树

最后的成品代码如下:

var isSubtree = function(root, subRoot) {
    let flag = false;
    trave(root);
    return flag;

    function trave(node) {
        if (node == null || flag == true) return;
        if (node.val == subRoot.val) {
            flag = check(node, subRoot);
        }
        trave(node.left);
        trave(node.right);
    }

    function check(n1, n2) {
        if (n1 == null && n2 == null) return true;
        if (n1 == null || n2 == null) return false;
        if (n1.val == n2.val) {
            return check(n1.left, n2.left) && check(n1.right, n2.right);
        } else {
            return false;
        }
    }
};

image.png