50-leetCode: 剑指 Offer 26. 树的子结构

129 阅读2分钟

题目

输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如: 给定的树 A:

     3     /
4   5   /
1   2 给定的树 B:

   4    /  1 返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

示例

输入: A = [1,2,3], B = [3,1]
输出: false

输入: A = [3,4,5,1,2], B = [4,1]
输出: true

解题思路

首先在A树上找到B树的根节点,如果找不到,那么肯定不是子树了;找到A中B的根节点后,再判断B是不是A的子树,如果不是就继续遍历A,同样去找A中的B树根节点,这就是一个递归过程。判断B是不是A的子树有四种情况, 1:左子树有,右子树有,值不一样,return false,否则递归子树;2:左子树无右子树有,return false, 3:左子树有,右子树无,return true,4:左子树无,右子树无,return true。

/**
 * Definition for a binary tree node.
 * function TreeNode(val) {
 *     this.val = val;
 *     this.left = this.right = null;
 * }
 */
/**
 * @param {TreeNode} A
 * @param {TreeNode} B
 * @return {boolean}
 */
var isSubStructure = function(A, B) {
    // 如果B为空节点直接返回false
    if (!B) return false;

    // 递归深度遍历查看B的根节点是否在A中
    function dfs(node) {
        // 传入根节点为空直接返回false,说明没有找到B的根节点在A中
        if (!node) return false;
        // 如果传入节点值与B根节点值相等,并且子树通过对比也相等,说明是子树;
        if (node.val === B.val && compare(node, B)) return true;
        // 返回遍历左右子树的结果
        return dfs(node.left) || dfs(node.right);
    }

    // 对比B树是否是A树的子树:四种情况
    function compare(nodeA, nodeB) {
        // A节点和B节点都有值
        if (nodeA && nodeB) {
            // 值不相等返回false
            if (nodeA.val !== nodeB.val) return false;
            // 值相等,继续递归遍历其子节点是否为子树
            return compare(nodeA.left, nodeB.left) && compare(nodeA.right, nodeB.right);
        }

        // A节点没值,B有值,那肯定不是
        if (!nodeA && nodeB) return false;

        // B节点没值,那么剩下的两种情况,A有值或没值,都满足条件
        return true;
    }

    // 返回递归结果
    return dfs(A);
};