树的子结构

树的子结构

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


这里要说一下这里的"子结构"和“子树”有什么区别。简单来说就是,子结构可以说子树或者子树的一部分,它也要求和原树的对应是连续的,但是可以不到叶子层

思路:用递归来实现,从 A 树的根节点开始,判断其所有的节点是不是依次和树 B 相同,如不同,递归调用函数,继续判断树 A 当前节点的左子树的所有节点或右子树的所有节点是否和树 B 所有节点相同,直到遍历到父树 A 的叶子节点,如果不是完全相同,则树 B 不是树 A 子树,如果直到遍历到树 B 的叶子节点,其所有节点在树 A 中均有,则树 B 是树 A 的子树。

isSubtree(root1 , root2) || HasSubtree(root1.left , root2) || HasSubtree(root1.right , root2);

// 判断树 A 所有的节点是不是依次和树 B 相同,或树 A 的左子树的所有节点或右子树的所有节点 是否和树 B 所有节点相同

isSubtree (root1.left , root2.left) && isSubtree ( root1.right , root2.right );

/**
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;
        }
        /*
        这里必须用或,因为可能有多个地方“有可能”能对上,所以需要通过递归和或运算多处尝试,只要有一个能对上就是true.
        */
        return isSubtree(root1,root2)||HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2);
    }
    
    public boolean isSubtree(TreeNode root1,TreeNode root2){
        /*
        递归出口,如果递归到子树完了,就说明全部都对上了。如果是原树完了而子树没完,那就说明没对上
        */
        if(root2==null){
            return true;
        }
        if(root1==null){
            return false;
        }
        if(root1.val==root2.val){
            return isSubtree(root1.left,root2.left)&&isSubtree(root1.right,root2.right);
        }
        /*
        如果以上情况都不是,那就是没对上
        */
        return false;
    }
}

这种二叉树类型的问题,使用递归最适合,但是非递归有时也必须会

注意,上面的写法是有讲究的:

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

不能换成:

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

if先判断哪个,后判断哪个,都是有隐含意义的:先判断root2,只要它为null,则无论root1是否是null都是配对完成了,但是先判断root1的话会错判root2同时为null的情况。这一点要注意。


我又重写了一下,对算法有了一些更好的思考,能够从算法设计的角度来理解了

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

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

    }

}
*/
public class Solution {
    //重造一个函数用于递归是为了避免开始时候检测root2是否为空和递归时检测root2是否为空的逻辑相反造成冲突
    public boolean HasSubtree2(TreeNode root1,TreeNode root2){
        if(root1==null){
            if(root2==null){
                return true;
            }else{
                return false;
            }
        }
        //递归中,root2是null是true的条件,和初始时是相反的
        if(root2==null){
            return true;
        }
        if(root1.val==root2.val){
            return ((HasSubtree2(root1.left,root2.left)&&HasSubtree2(root1.right,root2.right))||HasSubtree2(root1.left,root2)||HasSubtree2(root1.right,root2));
        }else{
            return (HasSubtree2(root1.left,root2)||HasSubtree2(root1.right,root2));
        }
    }
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        //初始时对特殊情况进行检测
        //初始时要求root2不能是null
        if(root2==null){
            return false;
        }
        if(root1==null){
            return false;
        }
        return HasSubtree2(root1,root2);
    }
}
posted @ 2020-03-02 16:39  别再闹了  阅读(137)  评论(0)    收藏  举报