思路整理自劍指Offer
一:題目描述
輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)
二:解題思路
要查找樹A中找到和樹B結構一樣的子樹:
第一步:在樹A中找到和B的根節點的值一樣的結點R
第二步:判斷樹A中以R爲根節點的子樹是不是包含樹B一樣的結構
以一個例子進行說明:
1.我們在樹A中找到值爲8的結點:從A的根節點開始遍歷,我們發現它的根節點的值就是8
2.接着我們就去判斷樹A的根節點下面的子樹是否含有和樹B一樣的結構。
3.在樹A中,根節點的左子樹的值是8,而樹B的根節點的左子樹結點是9,對應的兩個結點不同。
4.因此我們仍然要遍歷樹A,接着查找的值爲8的結點,我們在樹的第二層找到一個值爲8的結點
5.判斷該結點下面的子樹是否含有和B樹一樣結構的子樹,先後找到兩個結點9,2,這和樹B的結構完全相同。因此樹B是樹A的子結構
以一個例子說明:
三:代碼實現
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
bool DoesTree1HaveTree2(TreeNode* pRoot1, TreeNode* pRoot2){
//樹B遍歷完,則說明樹B是以pRoot爲根節點的子樹,是A的子樹
if(pRoot2==NULL)
return true;
//如果B還沒有遍歷結束,pRoot1就已經遍歷完,則B不是子樹
if(pRoot1==NULL)
return false;
//如果對應結點不相等,則B不是子樹
if(pRoot1->val!=pRoot2->val)
return false;
//如果當前對應結點符合條件,則分別遍歷左子結點和右子節點
return DoesTree1HaveTree2(pRoot1->left,pRoot2->left) && DoesTree1HaveTree2(pRoot1->right,pRoot2->right);
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
bool result=false;
//在每一處需要訪問地址的時候都要問自己這個地址有沒有可能是NULL,如果是NULL,如何處理
if(pRoot1==NULL || pRoot2==NULL)
return result;
//如果A的R節點與B的根節點相同,那麼我們要判斷A中以R結點爲根節點的子樹是否包含和樹B一樣的結構
if(pRoot1->val==pRoot2->val)
result=DoesTree1HaveTree2(pRoot1,pRoot2);
//如果R爲根節點的子樹不包含B,則繼續遍歷A,尋找與B樹根節點相同的結點
//左子結點
if(!result)
result=HasSubtree(pRoot1->left,pRoot2);
//右子節點
if(!result)
result=HasSubtree(pRoot1->right,pRoot2);
return result;
}
};