有兩個不同大小的二進制樹: T1 有上百萬的節點; T2 有好幾百的節點。請設計一種算法,判定 T2 是否爲 T1的子樹。
注意事項:若 T1 中存在從節點 n 開始的子樹與 T2 相同,我們稱 T2 是 T1 的子樹。也就是說,如果在 T1 節點 n 處將樹砍斷,砍斷的部分將與 T2 完全相同。
我的代碼
我的思路主要是運用遞歸的思想,具體流程分爲以下幾步:
//上面應有流程圖的...
/**
* 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;
}