LintCode 245 子树 出现错误的一些思考

有两个不同大小的二进制树: T1 有上百万的节点; T2 有好几百的节点。请设计一种算法,判定 T2 是否为 T1的子树。

注意事项:若 T1 中存在从节点 n 开始的子树与 T2 相同,我们称 T2 是 T1 的子树。也就是说,如果在 T1 节点 n 处将树砍断,砍断的部分将与 T2 完全相同。

我的代码

我的思路主要是运用递归的思想,具体流程分为以下几步:

Created with Raphaël 2.1.0
//上面应有流程图的...
/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     * @param T1, T2: The roots of binary tree.
     * @return: True if T2 is a subtree of T1, or false.
     */
    public boolean isSubtree(TreeNode T1, TreeNode T2) {
        // write your code here
        if (T1 == null&& T2!=null)
        {
            return false;
        }
        if (T2 == null)
        {
            return true;
        }
        if (T1.val == T2.val)
        {
            if (isSubtree(T1.left , T2.left)&&isSubtree(T1.right , T2.right))
            {
                return true;
            }
            else
            {
                TreeNode T1l = T1.left;
                TreeNode T1r = T1.right;
                if(isSubtree(T1l , T2)||isSubtree(T1r,T2))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
        else
        {
                TreeNode T1l = T1.left;
                TreeNode T1r = T1.right;
                if (isSubtree(T1l , T2)||isSubtree(T1r,T2))
                {
                    return true;
                }
                else
                {
                    return false;
                }  
        }
    }
}

然后提交代码,运行到了(80%),也就是测试集如下时,返回来了个true,其实答案是false(答案来自lintCode,未验证)。
其实这道题目挺简单,但是遇到这个问题一下子就激起我的好奇心了,调试了很久,改if啊改return啊改了半天,代码搞乱了连80%都跑不到了…

//训练集
{9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9}, {9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9}

仔细一想应该是我还有些应该注意到的问题没有注意,在网上搜寻了大家的答案:
以下是搜到的c++代码改写成java的代码:

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     * @param T1, T2: The roots of binary tree.
     * @return: True if T2 is a subtree of T1, or false.
     */
    public boolean isSubtree(TreeNode T1, TreeNode T2) {
        // write your code here
        boolean result = false;
        if(T2 == null)
        {
            return true;
        }
    if (T1 != null && T2 != null)
    {
        if (T1.val == T2.val)
            result = IsPart(T1, T2);
        if (!result)
            result = isSubtree(T1.left, T2);
        if (!result)
            result = isSubtree(T1.right, T2);
    }
    return result;
    }
    public boolean IsPart(TreeNode root1, TreeNode root2)
{
    if (root2 == null)
        return true;
    if (root1 == null)
        return false;
    if (root1.val != root2.val)
        return false;
    return IsPart(root1.left, root2.left) &&
        IsPart(root1.right, root2.right);
}
}

可见他设置了两个函数,isPart的目的是定根对比子树,isSubtree是定子树对比根,也就是说如果根节点的val相等时,他就跳入到isPart中进行计算,若isPart返回false就再对其子树进行计算。

分开了这两部分,他的代码比我的优雅的多,这也坚定了我刷完lintCode后还是回去刷leetCode的决心,后者至少有论坛可以看看大家的简洁代码。

然而在我运行后,结果还是一样的,卡在了80%,训练集还是之前的‘999’训练集。

cnBlog的答案

又找了会解决方案后在这道题目上已经浪费很长时间了…只能希望之后面TX不会碰到这种尴尬的情况。

不说了 上代码

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     * @param T1, T2: The roots of binary tree.
     * @return: True if T2 is a subtree of T1, or false.
     */
    public boolean isSubtree(TreeNode T1, TreeNode T2) {
        // write your code here
        if(T1==null && T2==null)
            return true;
        if(T1==null)
            return false;
        if(T2==null)
            return true;

        if(T1.val==T2.val){
            boolean res = isEqual(T1,T2);
            if(res)
                return true;
        }

        boolean lft = isSubtree(T1.left,T2);
        if(lft==true)
            return true;
        boolean rit = isSubtree(T1.right,T2);
        return rit;
    }
    public boolean isEqual(TreeNode T1,TreeNode T2){
        if(T1==null && T2==null)
            return true;
        if(T1==null)
            return false;
        if(T2==null)
            return false;
        if(T1.val==T2.val){
            boolean lft = isEqual(T1.left,T2.left);
            boolean rit = isEqual(T1.right,T2.right);
            if(lft && rit)
                return true;
        }
        return false;
    }
}

提交后居然AC了,那么问题出在哪里呢?
我觉得是出在判断条件:

 if(T1==null && T2==null)
            return true;
 if(T1==null)
            return false;
 if(T2==null)
            return true;

根据这个思路修改了我的代码后,居然还是不能AC…

不错 还是有点收获的

待续,我再去研究下。

  • 附 Lilian_Chan的答案
if(T2==nullptr && T1==nullptr)
return true;
第二个函数必须在T2、T1同时为NULL时才返回true,否则AC不了,下面AC的代码(C++)
bool isSubtree(TreeNode *T1, TreeNode *T2) { 
bool result = false; 
if (T2 == nullptr) 
{ 
    return true; 
} 
if (T1 == nullptr) 
{ 
    return false; 
} 

if (T1->val == T2->val) { 
    result = hasSubtree(T1,T2); 
} 
if (!result) { 
    result = isSubtree(T1->left,T2); 
} 
if (!result) { 
    result = isSubtree(T1->right,T2); 
} 
    return result; 
} 


bool hasSubtree(TreeNode *T1, TreeNode *T2)
{
    if(T2==nullptr && T1==nullptr)
    return true;

    if (T1 != nullptr && T2!=nullptr && T1->val == T2->val)
    {
            return hasSubtree(T1->left,T2->left) && hasSubtree(T1->right,T2->right);
    }
    return false;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章