【剑指offer】二叉树的子树

    xiaoxiao2021-12-03  20

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

    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; }
    转载请注明原文地址: https://ju.6miu.com/read-680110.html

    最新回复(0)