ch4.6: find the LCA of 2 nodes in a binary tree with 3 different methods

本文介绍了一种寻找二叉树中两个节点的最低公共祖先(LCA)的有效算法。通过三种不同方法实现:使用哈希表存储父节点、递归搜索共同父节点及从根节点开始的递归方法。提供了完整的代码示例并解释了每种方法的工作原理。

In this problem, it is important to fully understand the definition of least common ancestor of 2 nodes:

it means: (from leetcode blog: 点击打开链接)

        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4

If you are not so sure about the definition of lowest common ancestor (LCA), please refer to my previous post:Lowest Common Ancestor of a Binary Search Tree (BST) or the definition of LCA here. Using the tree above as an example, the LCA of nodes 5 and 1 is 3. Please note that LCA for nodes 5 and 4 is 5.


Here is the whole code with comments. Really good design by Hawstein.

// Ch4.6: Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. 
// Avoid storing additional nodes in a data structure. NOTE: This is not necessarily a binary search tree.

//http://leetcode.com/2011/07/lowest-common-ancestor-of-a-binary-tree-part-i.html
//the LCA of nodes 5 and 1 is 3. Please note that LCA for nodes 5 and 4 is 5.

#include 
  
   
#include 
   
    
#include 
    
     
#include 
     
using namespace std;

class BinNode{
public:
    int key;
    BinNode *parent, *lChild, *rChild;
    BinNode(){}
    BinNode(int t): key(t), parent(NULL), lChild(NULL), rChild(NULL){}
};

class BTree{
private:
    BinNode *m_root;
public:
    BTree(): m_root(NULL){}
    BTree(BinNode *t): m_root(t){}

    BinNode* getRoot() const{return m_root;}
    
    BinNode* balanceTree(BinNode* pnode, BinNode *parent, int *arr, int low, int high){
        if(low>high || arr == NULL)
            return NULL;
        int mid = (low+high)>>1;
        pnode = new BinNode(arr[mid]);
        pnode->parent = parent;
        pnode->lChild = balanceTree(pnode->lChild, pnode, arr, low, mid-1);
        pnode->rChild = balanceTree(pnode->rChild, pnode, arr, mid+1, high);

        return pnode;
    }

    void PrintPre(BinNode *pnode)
    {
        if(pnode == NULL)
            return;
 
        cout << pnode->key << " ";
        PrintPre(pnode->lChild);
        PrintPre(pnode->rChild);        
    }

    BinNode* minimal(BinNode* pnode){
        if(pnode==NULL) return NULL;
        while(pnode->lChild){
            pnode = pnode->lChild;
        }
        return pnode;
    }

    BinNode* successor(BinNode* qnode){
        if(qnode==NULL) return NULL;
        if(qnode->rChild) return minimal(qnode->rChild);
        BinNode *r = qnode->parent;
        while(r && r->rChild==qnode){
            qnode = r;
            r = r->parent;
        }
        return r;
    }
//  method 1: use a hash table to store the n1's parent to see if n2's parents are 
//  in the map. Learn to use map: key: pointer to the value, mapped value: the real data
    BinNode* firstAns(BinNode *n1, BinNode *n2){
        if(n1==NULL || n2==NULL) return NULL;
        map
      
        m;
        while(n1){
            m[n1] = true;
            n1=n1->parent;
        }
        while(n2 && !m[n2]){
            n2 = n2->parent;
        }
        return n2;
    }

//  method 2: recursively search for the commen father of (n1,n2). 
//  father method is use to see if (n1,n2) share the same father by going down:
//  n1->child->child->...->child. Only modify n1;
//  in the LCA recursively move n1 up 1 step until find (n1->p->p->...->p,n2) 
//  the same father. only modify n1;
//  By combining these 2 methods(one goes down, one goes up), n1 will search all the 
//  nodes in the tree to find the LCA to n2;
    bool father(BinNode *n1, BinNode *n2){
        if(n1==NULL || n2==NULL) return false;
        else if (n1==n2) return true;
        return (father(n1->lChild, n2) || father(n1->rChild, n2));
    }

    BinNode* firstAns2(BinNode *n1, BinNode *n2){
        if (n1==NULL || n2==NULL) return NULL;
        while(n1){
            if(father(n1,n2)) return n1;
            n1=n1->parent;
        }
        return NULL; // don't forget it.
    }

/*  method 3: if the node doesn't contain parent pointer(just don't use ->parent),
    then we can start from root and recursively. Carefully read the solution,: how 
    to update head, res. Use Node* &res, call by reference so will modify ans.
*/
    void firstAns3(BinNode *head, BinNode *n1, BinNode *n2, BinNode* &res){
        if (head==NULL || n1==NULL || n2==NULL) return;
        if(head && father(head, n1) && father(head, n2)){
            res = head;
            firstAns3(head->lChild, n1, n2, res);
            firstAns3(head->rChild, n1, n2, res);
        }
    }



// Auxilary methods:
    BinNode* searchND(BinNode* x_head, int x){
        if(x_head==NULL) return NULL;
        else if(x==x_head->key) return x_head;
        else if(x<=x_head->key) searchND(x_head->lChild, x);
        else searchND(x_head->rChild, x);
    }

    vector
       
        
         > BFSlist(BinNode *head){ vector
         
          
           > res; int level = 0; list
           
             li; li.push_back(head); res.push_back(li); while(!res[level].empty()){ list
            
              l; list
             
              ::iterator it; for(it=res[level].begin(); it!=res[level].end(); ++it){ BinNode *n = *it; if(n->lChild) l.push_back(n->lChild); if(n->rChild) l.push_back(n->rChild); } ++level; res.push_back(l); } return res; } void print(vector
              
               
                 > res){ vector
                
                 
                   >::iterator vit; for(vit=res.begin(); vit!=res.end(); ++vit){ list
                  
                    li = *vit; list
                   
                    ::iterator lit; for(lit=li.begin(); lit!=li.end(); ++lit){ BinNode *n = *lit; cout<
                    
                     key<<" "; } cout<
                     
                      balanceTree(bt->getRoot(), NULL, arr, low, high); bt = new BTree(proot); bt->PrintPre(bt->getRoot()); cout << "pnode is: "<< proot->key<
                      
                       successor(proot))->key<
                       
                        > jerry = bt->BFSlist(proot); bt->print(jerry); BinNode *n1 = bt->searchND(proot, 13); BinNode *n2 = bt->searchND(proot, 22); BinNode *n1_n2_ans = bt->firstAns(n1, n2); cout<
                        
                         key<<" "<
                         
                          key<
                          
                           key<
                           
                            firstAns2(n1, n2); cout<
                            
                             key<
                             
                              firstAns3(proot, n1, n2, result); cout<
                              
                               key<
                               
                              
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
        
       
      
    
   
  

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值