給定兩個樹節點,返回這兩個節點最近的一個公共父節點。
二叉搜索樹
struct BinaryTreeNode{
int val;
BinaryTreeNode* left;
BinaryTreeNode* right;
BinaryTreeNode(int num):val(num),left(NULL),right(NULL){}
}
BinaryTreeNode* FindSC(BinaryTreeNode* root,BinaryTreeNode* a,BinaryTreeNode* b){
if(root==NULL)//根節點爲空,說明這樹不存在,那麼兩個節點就不可能會有公共祖先
return NULL;
//如果給定的兩個節點中有一個爲空,那麼公共祖先就是其中的一個不爲空的節點
if(a==NULL)
return b;
else if(b==NULL)
return a;
if(a->val<root->val&&b->val<root->val)
return FindSC(root->left,a,b);
else if(a->val>root->val&&b->val>root->val)
return FindSC(root->right,a,b);
else
return root;
}
對於二叉搜索樹來說,還是非常trivial的,首先我們遍歷根節點,判斷兩個給定節點的val是大於還是小於根節點的val,如果都小於,那麼都在左子樹,這時候我們就遍歷左孩子,如果都大於,那麼說明兩個節點都在右子樹,這時候我們就遍歷右孩子,如果一個在左邊一個在右邊,那麼說明root就是他們的最近公共祖先了。
普通樹,但是每個節點包含有指向父節點的指針
既然包含有指向父節點的指針,那麼說明從根節點到給定節點的路徑是一個雙向鏈表,所以問題就轉化爲求兩個雙向鏈表的交點。
struct TreeNode{
int val;
TreeNode* parent;
TreeNode* left;
TreeNode* right;
}
//返回當前節點所在的高度
int countheight(TreeNode* root,TreeNode* A){
int count=0;
TreeNode* temp = A;
while(temp!=root){
++count;
temp = temp->parent;
}
return count;
}
TreeNode* findlst(TreeNode* root,TreeNode* A,TreeNode* B){
if(root==NULL)
return NULL;
if(A==NULL)
return B;
else if(B==NULL)
return A;
int heighta = countheight(root,A);
int heightb = countheight(root,B);
if(heighta>heightb){
TreeNode* temp = A;
A = B;
B=temp;
}
int i=0;
TreeNode* temp = B;
while(i<abs(heighta-heightb)){
temp = temp->parent;
++i;
}
while(temp!=A){
temp=temp->parent;
A = A->parent;
}
return temp;
}
首先我們分別計算出兩個節點各自所在height,然後一個同時向父節點移動,第一個相等的節點就是交點,也就是我們討論的最近公共祖先節點。
普通樹
難度繼續增加,有麼有???先上代碼
bool getNodePath(TreeNode* root,TreeNode* node,list<TreeNode*>& path){
if(root==node)
return true;
path.push_back(root);
bool found=false;
vector<TreeNode*>::iterator i=root->children.begin();
while(!found&&i!=root->children.end()){
found = getNodePath(*i,node,path);
++i;
}
if(found==false)
path.pop_back();
return found;
}
TreeNode* common(TreeNode* root,TreeNode* node,TreeNode* node1){
list<TreeNode*> path1,path2;
getNodepath(root,node,path1);
getNodepath(root,node1,path2);
list<TreeNode*>::iterator i1 = path1.begin();
list<TreeNode*>::iterator i2 = path2.begin();
TreeNode* plast = NULL;
while(i1!=path1.end()&&i2!=path2.end()){
if(*i1==*i2)
plast = *i1;
++i1;
++i2;
}
return plast;
}
使用額外的輔助空間存放從根節點到子節點的路徑,得到兩個鏈表
然後遍歷連個鏈表,獲得最近的交點。需要遍歷兩次樹。