树的子结构 、子树

自己通过的牛客网的代码

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1 == null || root2 == null){
            return false;
        }
        if (root1 == root2) {
             return true;
        }
        boolean result = false;

        if(root1.val == root2.val){
            result = isSame(root1,root2);
        }
        if (result) {
            return true;
        }
        return HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2);
    }
    public boolean isSame(TreeNode root1,TreeNode root2){
        if(root1 == root2){
            return true;
        }
        if(root2 == null){
            return true;
        }
        if(root1 == null){
            return false;
        }
        if (root1.val == root2.val) {
            return isSame(root1.left,root2.left) && isSame(root1.right,root2.right);
        }
        return false;
    }
}

题目

输入两颗二叉A,B,判断B是不是A的子结构。(PS:我们约定空树不是任意一个树的子结构)。

思路

要查找树A中是否存在和树B结构一样的子树,我们可以分为两步:第一步在树A中找到和B的根结点的值一样的结点R,第二步再判断树A中以R为根节点的子树是不是包含和树B一样的结构。

这里使用递归的方法即可。

代码

/**
 * 输入两棵二叉树A和B,判断B是不是A的子结构。
 * 该方法是在A树中找到一个与B树的根节点相等的元素的结点,
 * 从这个相等的结点开始判断树B是不是树A的子结构,如果找到其的一个就返回,
 * 否则直到所有的结点都找完为止。
 *
 * @param root1 树A的根结点
 * @param root2 树B的根结点
 * @return true:树B是树A的子结构,false:树B是不树A的子结构
 */
public static boolean hasSubtree(TreeNode root1, TreeNode root2) {
    // 只要两个对象是同一个就返回true
    // 【注意此处与书本上的不同,书本上的没有这一步】
    if (root1 == root2) {
        return true;
    }

    // 只要树B的根结点点为空就返回true
    if (root2 == null) {
        return true;
    }

    // 树B的根结点不为空,如果树A的根结点为空就返回false
    if (root1 == null) {
        return false;
    }

    // 记录匹配结果
    boolean result = false;

    // 如果结点的值相等就,调用匹配方法
    if (root1.value == root2.value) {
        result = match(root1, root2);
    }

    // 如果匹配就直接返回结果
    if (result) {
        return true;
    }

    // 如果不匹配就找树A的左子结点和右子结点进行判断
    return hasSubtree(root1.left, root2) || hasSubtree(root1.right, root2);
}

/**
 * 从树A根结点root1和树B根结点root2开始,一个一个元素进行判断,判断B是不是A的子结构
 *
 * @param root1 树A开始匹配的根结点
 * @param root2 树B开始匹配的根结点
 * @return 树B是树A的子结构,false:树B是不树A的子结构
 */
public static boolean match(TreeNode root1, TreeNode root2) {
    // 只要两个对象是同一个就返回true
    if (root1 == root2) {
        return true;
    }

    // 只要树B的根结点点为空就返回true
    if (root2 == null) {
        return true;
    }
    // 树B的根结点不为空,如果树A的根结点为空就返回false
    if (root1 == null) {
        return false;
    }

    // 如果两个结点的值相等,则分别判断其左子结点和右子结点
    if (root1.value == root2.value) {
        return match(root1.left, root2.left) && match(root1.right, root2.right);
    }

    // 结点值不相等返回false
    return false;
}
public class Solution {
    //先从根开始再把左作为根,再把右作为根由本函数决定。把一个为根的时候的具体比对过程是第二个函数决定。
    //从根可以认为是一颗树,从左子树开始又可以认为是另外一颗树,从右子树开始又是另外一棵树。
    //本函数就是判断这一整颗树包不包含树2,如果从根开始的不包含,就从左子树作为根节点开始判断,
    //再不包含从右子树作为根节点开始判断。
    //是整体算法递归流程控制。
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean res = false;
        if (root1 != null && root2 != null) {
            if(root1.value == root2.value){
                res = doesTree1haveTree2(root1,root2);
            }
            if(!res)
            {
                res = HasSubtree(root1.left, root2);
            }
            if(!res)
            {
                res = HasSubtree(root1.right, root2);
            }
        }
        return res;
    }
    //本函数,判断从当前的节点 ,开始两个树能不能对应上,是具体的比对过程
    public boolean doesTree1haveTree2(TreeNode root1,TreeNode root2) {
        if(root2 == null)
        {
            return true;
        }
        if(root1 == null)
        {
            return false;
        }
        if(root1.value != root2.value){
            return false;
        }
        //如果根节点可以对应上,那么就去分别比对左子树和右子树是否对应上
        return doesTree1haveTree2(root1.left, root2.left) && doesTree1haveTree2(root1.right, root2.right);
    }

 

子树

LeetCode

以上代码1在LeetCode中不通过 (因为上面是子结构)  LeetCode是子树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSubtree(TreeNode root1, TreeNode root2) {
         // 只要两个对象是同一个就返回true
        // 【注意此处与书本上的不同,书本上的没有这一步】
        if (root1 == root2) {
            return true;
        }

        // 只要树B的根结点点为空就返回true
        if (root2 == null) {
            return true;
        }

        // 树B的根结点不为空,如果树A的根结点为空就返回false
        if (root1 == null) {
            return false;
        }

        // 记录匹配结果
        boolean result = false;

        // 如果结点的值相等就,调用匹配方法
        if (root1.val == root2.val) {
            result = match(root1, root2);
        }

        // 如果匹配就直接返回结果
        if (result) {
            return true;
        }

        // 如果不匹配就找树A的左子结点和右子结点进行判断
        return isSubtree(root1.left, root2) || isSubtree(root1.right, root2);
    }
    public boolean match(TreeNode root1, TreeNode root2) {
        // 只要两个对象是同一个就返回true
        if (root1 == root2) {
            return true;
        }
        if(root2 == null && root1 == null){
            return true;
        }
        if (root1 == null || root2== null) {
            return false;
        }
        // 如果两个结点的值相等,则分别判断其左子结点和右子结点
        if (root1.val == root2.val) {
            return match(root1.left, root2.left) && match(root1.right, root2.right);
        }

        // 结点值不相等返回false
        return false;
    }
}

 

其实两个题的区别就是


        if(root2 == null){
            return true;
        }
        if(root1 == null){
            return false;
        }



        if(root1 == null && root2 == null){
            return true;
        }
        if (root2 == null && root1 != null) {
            return false;
        }
        if (root2 != null && root1 == null) {
            return false;
        }