树中节点最低公共祖先

给定两个树节点,返回这两个节点最近的一个公共父节点。

二叉搜索树

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;
}

使用额外的辅助空间存放从根节点到子节点的路径,得到两个链表
然后遍历连个链表,获得最近的交点。需要遍历两次树。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值