第二次看到这个题还是不会....参考了这道题牛客网排名第一的答案,在理解的过程中,我认为这个答案有问题,如果是我理解错了,欢迎讨论指正。
关于树的子结构的定义,网上也没有很明确的说法,个人理解就是,只要小树是大树结构中的一部分就行。(子结构与子树一定要区分开来,最后会介绍两者区别。)
参考网上的博客得出的子树和子结构的区别:
子树的意思是包含了一个结点,就得包含这个结点下的所有节点,一棵大小为n的二叉树有n个子树,就是分别以每个结点为根的子树。子结构的意思是包含了一个结点,可以只取左子树或者右子树,或者都不取。
首先,根据剑指offer书上的测试用例,测试了牛客排名第一的答案。左边为大树,右边为小树,显然结果是true。
但是,他写的真的对吗?
按下面的代码构建两棵树进行测试,
/*
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
*/
public static void main(String[] args) {
TreeNode root =new TreeNode(8);//大树根节点
TreeNode r1=new TreeNode(8);
TreeNode r2=new TreeNode(2);
root.right=r2;
root.left=r1;
TreeNode r3=new TreeNode(9);
TreeNode r4=new TreeNode(7);
r1.right=r4;
r1.left=r3;
TreeNode target=new TreeNode(8);//小树根节点
target.left=new TreeNode(9);
target.right=new TreeNode(2);
System.out.println(new Offer17().HasSubtree(root,target));
}
即下图两棵树,显然右边不是左边的子结构,但是按他的代码却返回true。
这里贴出这位兄台的代码:
public class Solution {
public boolean HasSubtree(TreeNode root1, TreeNode root2) {
if (root1 == null || root2 == null) {
return false;
}
return judgeSubTree(root1, root2) ||
judgeSubTree(root1.left, root2) ||
judgeSubTree(root1.right, root2);
}
private boolean judgeSubTree(TreeNode root1, TreeNode root2) {
if (root2 == null) {
return true;
}
if (root1 == null) {
return false;
}
if (root1.val != root2.val) {
return judgeSubTree(root1.left, root2) ||
judgeSubTree(root1.right, root2);
}
return judgeSubTree(root1.left, root2.left) &&
judgeSubTree(root1.right, root2.right);
}
}
在HasSubtree中的第一个judgeSubTree(root1, root2)就返回了true,显然错了。
其实思路应该分为两步:
1.在大树中找到和小树根节点相同的节点。
2.然后以此节点为根节点,在大树上往下搜索对比小书左右节点是否相同,不同则返回false
3.如果2步中最后返回false 回到第一步,从大树的左子树找和小树根节点相同的节点。
4.如果3步中最后返回false 回到第一步,从大树的右子树找和小树根节点相同的节点。
下面贴出按剑指Offer的代码,已测试通过。
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1==null||root2==null) return false;
boolean result=false;
if(root1.val==root2.val){
result = HasSubtreeHelper(root1,root2);
}
if(!result) result = HasSubtree(root1.left,root2);
if(!result) result = HasSubtree(root1.right,root2);
return result;
}
public boolean HasSubtreeHelper(TreeNode r1,TreeNode r2){
if(r2==null) return true;
if(r1==null) return false;
if(r1.val!=r2.val) return false;
return HasSubtreeHelper(r1.left,r2.left)&&HasSubtreeHelper(r1.right,r2.right);
}