判断二叉树是否为子树

这里写图片描述

这里写图片描述

  • 之前写过先序遍历和中序遍历去推导二叉树的java实现,这次是判断root2是否为root1的子树结构。我想到是用遍历节点和递归去解决,主要就是要解决指针(java里的引用)滑动遍历问题和递归出口问题,但是题目没有明确空树是否算是子树,这几个可能性只能通过在编写完核心代码后调试命题者的意思,这只要留心一下就行了。
  • 想到过用遍历去比较,但是并没理清思路,后来还是参考了网上的代码,用循环和递归混合去解决问题虽然代码简洁,但是理解起来还是难度比较大。先实现功能吧。
  • 首先查找到root1树的值与root2的值相等的那个节点,然后再去比较是否为子树。这个思路是比较清晰的。比较是否为子树可以构造一个方法isTree。但是要注意在root1中如果找到相同的节点后后无法完全匹配到子树,那root1中的指针还是要继续滑动,不能终止程序,可能后面还能匹配上这样就丢解了。
  • 下面贴出代码:
    public static boolean HasSubtree(TreeNode root1,TreeNode root2)
    {
//      boolean result = false;
        //递归的解决方案
        /*
         * 先找到与root2相同值的节点
         * 再调用函数判断是否为子树
         */
        TreeNode p1 = root1;
        //若可能的子树为空
        if(root2 == null)
        {
            return true;
        }
        //若被比较的树为空
        if(p1 == null)
        {
            return false;
        }
        //若两个值相等
        if(p1.val == root2.val)
        {
            /*
             * 最开始我是直接使用return isTree(p1,root2)
             * 但是直接返回false,丢掉了后面可能的解
             */
            //改进后的方法,可以直接归并到外层判断里,这里只为直观
            if(isTree(p1, root2))
            {
                return true;
            }

        }
        //若不相等,滑动指针
        if(p1.left != null && p1.right == null)
        {
            p1 = p1.left;
            return HasSubtree(p1, root2);
        }
        if(p1.right != null && p1.left == null)
        {
            p1 = p1.right;
            return HasSubtree(p1, root2);
        }
        //值不相等,而且p1左右子树均不为空
        if(p1.left != null && p1.right != null)
        {
            return HasSubtree(p1.left, root2)||HasSubtree(p1.right, root2);
        }
        return false;
    }
    //根节值相等,判断是否为子树
    private static boolean isTree(TreeNode root1,TreeNode root2)
    {
        if(root2.left == null && root2.right == null)
        {
            return true;
        }
        if(root2.left != null && root2.right == null)
        {
            if(root1.left == null)
            {
                return false;
            }
            if(root2.left.val == root1.left.val)
            {
                return isTree(root1.left, root2.left);
            }
        }
        if(root2.right != null && root2.left == null)
        {
            if(root1.right == null)
            {
                return false;
            }
            if(root2.right.val == root1.right.val)
            {
                return isTree(root1.right, root2.right);
            }
        }
        if(root2.right != null && root2.right != null)
        {
            if(root1.left == null || root1.right == null)
            {
                return false;
            }
            if(root2.left.val == root1.left.val && root2.right.val == root1.right.val)
            {
                return isTree(root1.left, root2.left) && isTree(root1.right, root2.right);
            }
        }
        return false;
    }
}
//定义树节点
class TreeNode
{
    TreeNode left;
    TreeNode right;
    public int val;
    public TreeNode(int val)
    {
        this.val = val;
    }
}

成功实现!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值