要求分析:
1、第一次判断时,如果B为空,则返回空
2、先判断B根节点的值,如果B根节点的与A的根节点值相同,则判断A的左子树和B的左子树及A的右子树和B的右子树是为子结构关系。(递归)
3、直到判断到B的节点值与A的节点值相等,而B没有子树,则此时为其子结构
4、如果判断过程中,B树的前面部分都为A树从节点root1Now开始的一部分,但是最后出现了值不相等,或者B还有子树而A没有子树的情况,则A应该返回至root1Now的左右节点,B应该返回值最初的B。
代码
/**
public class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
*/
public class Solution {
TreeNode root1Now=new TreeNode(0);
TreeNode root2Root=new TreeNode(0);
boolean newStart=true;
boolean begin=true;
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(begin==true)
{
if(root2==null)
{
return false;
}
else
{
begin=false;
return HasSubtree(root1,root2);
}
}
else
{
if(root2==null)
return true;
else
{
if(root1==null)
return false;
if(root1.val==root2.val)
{
if(newStart ==true)
{
root1Now=root1;
root2Root=root2;
}
newStart=false;
if(HasSubtree(root1.right,root2.right)&&HasSubtree(root1.left,root2.left))/*子树之间要都是对应的子节点*/
return true;
else
{
newStart=true;
root1=root1Now;
root2=root2Root;
return (HasSubtree(root1.right,root2)||HasSubtree(root1.left,root2));
}
}
else
{
if(newStart==false)/*判断是否开始了一次左右子树是否子结构的判断,如果开始了是否为左右
子结构的判断,但是又出现了不相等的情况,则应该直接返回false,然后从之前记录的位置重新
开始*/
{
return false;
}else return (HasSubtree(root1.right,root2)||HasSubtree(root1.left,root2));
}
}
}
}
}
注意事项(这里记录了我写代码时出现的bug,看懂以上代码的可以忽略)
关于递归的问题
关于递归有不同的调用情况
1、
return (HasSubtree(root1.right,root2)||HasSubtree(root1.left,root2));
这种是这个节点和root2的根节点值不相同,所以应该在root1的左右子树中继续找。
2、
if(HasSubtree(root1.right,root2.right)&&HasSubtree(root1.left,root2.left))/*子树之间要都是对应的子节点*/
return true;
这种情况是必须两者都是子结构,才能返回true。
但是在再次调用
HasSubtree(root1.right,root2.right)
这个函数的时候,复用了一段关于节点值不相等的时候应该的操作,那这个就应该分两种情况。
1、如果是在newStart的过程中,就是根节点相等,要判断子树的时候。出现了值不相等,则应该直接返回false,这样HasSubtree(root1.right,root2.right)的查找就会结束,就会退到之前开始的地方。
2、如果不是在newStart的过程中,就是一直在往下找一个相等的节点的时候,则就是直接往下寻找。
我的错误
我在第一种情况的时候,没有返回。而是直接回到了开始的地方,开始新的查找。
但是这时候,他还是属于
HasSubtree(root1.right,root2.right)&&HasSubtree(root1.left,root2.left)
这个过程中,也就是说,如果是这样,newStart的值会产生混乱。
root1=root1Now;
root2=root2Root;
的过程没有办法得到保证正确。
一次低级错误
begin是表示这是第一次执行该函数的标志,用于实现B一开始就是null时,直接返回false。
正确的代码如下:
if(begin==true)
{
if(root2==null)
{
return false;
}
else
{
begin=false;
return HasSubtree(root1,root2);
}
}
我写了一次错误代码为:
if(begin==true)
{
if(root2==null)
{
return false;
}
}
......
return false /*这里*/
后面的没变,但是提示说,缺一个返回,我就在最后随便写了个返回 return false ???
我也不知道我在想什么哦。实际这种问题就是提醒,在里面这个if里面,少了一种情况没有说明。
这里的情况是没有变化begin。这样子直接就是返回false了。这个是基础错误。
参考链接
https://www.nowcoder.com/profile/562667/codeBookDetail?submissionId=1523155