樹中節點最低公共祖先

給定兩個樹節點,返回這兩個節點最近的一個公共父節點。

二叉搜索樹

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

使用額外的輔助空間存放從根節點到子節點的路徑,得到兩個鏈表
然後遍歷連個鏈表,獲得最近的交點。需要遍歷兩次樹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章