參考鏈接:https://blog.csdn.net/nepenthe_csdn/article/details/52348194
這里說一下二叉樹的子樹和子結構的概念:
子樹的意思是包含了一個結點,就得包含這個結點下的所有節點,一棵大小為n的二叉樹有n個子樹,就是分別以每個結點為根的子樹。子結構的意思是包含了一個結點,可以只取左子樹或者右子樹,或者都不取。
基本的數據結構TreeNode:
struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) { } };
下面是判斷B是否是A的子樹的代碼:
bool IsSametree(TreeNode* pRoot1,TreeNode* pRoot2) { if(pRoot1==NULL&&pRoot2 == NULL)//同時達到葉子結點 return true; else return false; if(pRoot1->val == pRoot2->val) return IsSametree(pRoot1->left,pRoot2->left)&&IsSametree(pRoot1->right,pRoot2->right); else return false; } bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { if(pRoot2 == NULL) return false; else if(pRoot1 == NULL) return false; if(pRoot1->val == pRoot2->val) return IsSametree(pRoot1,pRoot2); if(pRoot1->val > pRoot2->val) return HasSubtree(pRoot1->left,pRoot2); if(pRoot1->val < pRoot2->val) return HasSubtree(pRoot1->right,pRoot2); }
下面是判斷B是否是A的子結構的代碼,相對於上面判斷是否是子樹的代碼稍微有所不同:
首先,遞歸返回的條件不一樣,當B到達了葉子結點,但是A沒有到葉子結點,也是正確的,這是和上題不一樣的地方。但是如果A先到葉子結點,就肯定不對,返回false。再者,因為不是二叉排序樹,所以結點的值沒有限制,如果不同的結點有相同的值,這就要注意了!可能找到和B根結點一樣的值,但是從該結點往下查看,發現結點沒有對應,不要直接返回false!因為可能有別的結點有相同的值,從該結點往下和B一樣!此時要設置一個標志位,當是子結構是返回true,當不是子結構時返回false,此時再去搜索A的下一個結點,繼續判斷。
class Solution { public: bool IsSubtree(TreeNode* pRoot1,TreeNode* pRoot2) { if(pRoot2==NULL) //B同時或先到達葉子結點 return true; else if(pRoot1 == NULL) return false; //B不是空,但A是空,說明A先到達葉子結點 if(pRoot1->val == pRoot2->val) return IsSubtree(pRoot1->left,pRoot2->left)&&IsSubtree(pRoot1->right,pRoot2->right); else return false; } bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2) { if(pRoot2 == NULL) return false; else if(pRoot1 == NULL) return false; // A先到達葉子結點 bool flag = false; if(pRoot1->val == pRoot2->val) flag = IsSubtree(pRoot1,pRoot2); if(!flag) flag = HasSubtree(pRoot1->left,pRoot2)||HasSubtree(pRoot1->right,pRoot2); return flag; } };