给定两个树节点,返回这两个节点最近的一个公共父节点。
二叉搜索树
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;
}
使用额外的辅助空间存放从根节点到子节点的路径,得到两个链表
然后遍历连个链表,获得最近的交点。需要遍历两次树。