【剑指offer】二叉树的子树

代码实现起来主要容易忽略两方面的问题。
第一版:

     public static boolean hasSubTree(TreeNode root1,TreeNode root2){
         if(root1==null||root2==null) return false;
         if(root1.val!=root2.val){
             return hasSubTree(root1.left,root2)||hasSubTree(root1.right,root2);
         }else{
             boolean hasLeft=true;
             if(root2.left!=null){
                 hasLeft=hasSubTree(root1.left,root2.left);
             }
             boolean hasRight=true;
             if(root2.right!=null){
                 hasRight=hasSubTree(root1.right,root2.right);
             }
             return true;
         }
     }

乍一看好像没什么问题,结果不能AC。仔细查看测试用例,发现忽略了root1中多次出现root2的根结点,并且子树出现在第二次或之后的情况。
第二版:

     public static boolean hasSubTree(TreeNode root1,TreeNode root2){
         if(root1==null||root2==null) return false;
         if(root1.val!=root2.val){
             return hasSubTree(root1.left,root2)||hasSubTree(root1.right,root2);
         }else{
             boolean hasLeft=true;
             if(root2.left!=null){
                 hasLeft=hasSubTree(root1.left,root2.left);
                 if(!hasLeft){
                     return hasSubTree(root1.left,root2);
                 }
             }
             boolean hasRight=true;
             if(root2.right!=null){
                 hasRight=hasSubTree(root1.right,root2.right);
                 if(!hasRight){
                     return hasSubTree(root2.right,root2);
                 }
             }
             return true;
         }
     }

结果还是不能AC,原因是这种判断是分解式而不是整体式的。比如root1={8,8,7,9,2},root2={8,9,2}在判断完根结点8之后,接着只会判断root1的左子树中是否含有9而不是左子结点是不是9,那么显然是含有的。继而函数只会判断root1的右子树是否包含2,而不会继续在左子树中搜索是否含有root2,从而给出错误判断。
第三版:
经过两次失败总算明白了,要不判断树是不是另一个树的子树,一定要先知道如何判断树不是另一棵树的直接子树。

     public static boolean hasSubTreeDirectly(TreeNode root1,TreeNode root2){
         if(root2==null) return true;
         if(root1==null) return false;
         if(root1.val!=root2.val) return false;
         return hasSubTreeDirectly(root1.left,root2.left)&&hasSubTreeDirectly(root1.right,root2.right);
     }

当遇到与root2根结点值相同的结点时,先看此结点是不是直接包含子树root2。如果结点值不相等或者不直接包含子树root2,则分别在其左右子树中继续查找。

     public static boolean hasSubTree(TreeNode root1,TreeNode root2){
         if(root1==null||root2==null) return false;
         boolean result=false;
         if(root1.val==root2.val){
             result=hasSubTreeDirectly(root1,root2);
         }
         if(!result){
             result=hasSubTree(root1.left,root2)||hasSubTree(root1.right,root2);
         }
         return result;
     }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值