输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

要求分析:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章