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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章