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

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< 
                                 
                                
                               
                              
                             
                            
                           
                          
                         
                        
                       
                      
                     
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值