1. 程式人生 > >求二叉樹中兩個節點的最小公共祖先(LCA)

求二叉樹中兩個節點的最小公共祖先(LCA)

題目要求:求二叉樹中兩個節點p,q的最低公共祖先節點

首先,題目中沒有明確說明節點的結構,所以思考了一會然後問面試官節點有沒有父指標,面試官說有沒有父指標有影響嗎?我說有,然後他笑著說你來說說看。當時,只做出來有父指標的情況,沒有父指標的情況壓根想不出來。後來會實驗室靜下心來很快就想到了思路。這裡分這兩種情況討論:

1. 二叉樹節點具有父指標

      在節點具有父指標的情況下,顯然此二叉樹就可以看成是通過父指標連線的"T"型連結串列,題目也就轉化成查詢"T"型連結串列的第一個公共節點。(可看做兩個連結串列相交,求連結串列相交的第一個公共節點)假設p,q分別為所求的兩個節點,則通過遍歷一遍可以知道p,q分別到根節點的長度pLen和qLen。這樣就知道pLen和qLen之間長度之差,也就知道p、q到它們的第一個公共祖先節點k長度之差L。因為p,q到根節點的路徑中都包含k到根節點的路徑,所以pLen和qLen之差等於p、q到k的長度之差。然後,讓p、q到根節點路徑長度大的先向前走L,然後長度小再和大的同時向前遍歷,當它們兩指向同一個節點時,則那個節點即是所求。

  1. /** 
  2.  * 有父指標情況下,查詢兩個節點的最低公共節點 
  3.  * @author chosen0ne 
  4.  * 2011-01-18 
  5.  */
  6. class BTree<T>{  
  7.     private BTNode<T> root;  
  8.     public BTree(BTNode<T> r){  
  9.         this.root=r;  
  10.     }  
  11.     /** 
  12.      * 查詢兩個節點的最低公共祖先節點 
  13.      * @param p  
  14.      * @param q 
  15.      * @return BTNode<T> 最低公共祖先節點,沒有找到返回null
     
  16.      */
  17.     public BTNode<T> findLowestAncestor(BTNode<T> p,BTNode<T> q){  
  18.         if(p==null||q==null)  
  19.             thrownew NullPointerException();  
  20.         int pLen=0,qLen=0;//p,q兩個節點到根節點的路徑長度
  21.         //計算p到根節點的長度
  22.         for(BTNode<T> ancestor=p.parent;ancestor!=null
    ;ancestor=ancestor.parent)  
  23.             pLen++;  
  24.         //計算q到根節點的長度
  25.         for(BTNode<T> ancestor=q.parent;ancestor!=null;ancestor=ancestor.parent)  
  26.             qLen++;  
  27.         //如果p到根節點的長度比q長,則讓p前進pLen-qLen
  28.         for(;pLen>qLen;pLen--)  
  29.             p=p.parent;  
  30.         //如果q到根節點的長度比p長,則讓q前進qLen-pLen
  31.         for(;qLen>pLen;qLen--)  
  32.             q=q.parent;  
  33.         //此時,p和q到根節點的長度相同。假設k是最近的公共節點,則p和q到k的長度相同
  34.         //p和q按照相同步長1向前遍歷,如果存在公共節點則p和去會同時指向它
  35.         while(q!=null&&p!=null&&p!=q){  
  36.             q=q.parent;  
  37.             p=p.parent;  
  38.         }  
  39.         if(p==q)  
  40.             return p;  
  41.         returnnull;  
  42.     }  
  43.     /** 
  44.      * 測試方法,在t中查詢a,b的最低公共祖先節點 
  45.      * @param t 
  46.      * @param a 
  47.      * @param b 
  48.      */
  49.     privatestatic<T> void test(BTree<T> t, BTNode<T> a, BTNode<T> b){  
  50.         BTree.BTNode<T> p=t.findLowestAncestor(b,a);  
  51.         if(p!=null)  
  52.             System.out.println(a.data+","+b.data+"的最低公共祖先節點是 :"+p.data);  
  53.         else
  54.             System.out.println(a.data+","+b.data+"沒有公共祖先節點");  
  55.     }  
  56.     publicstaticvoid main(String[] arg){  
  57.         /*  構造如下二叉樹 
  58.                         a 
  59.                      /    / 
  60.                     b     c 
  61.                   /   /   /  / 
  62.                 d     e f    g 
  63.         */
  64.         BTree.BTNode<String> g=new BTree.BTNode().data("g");  
  65.         BTree.BTNode<String> f=new BTree.BTNode().data("f");  
  66.         BTree.BTNode<String> e=new BTree.BTNode().data("e");  
  67.         BTree.BTNode<String> d=new BTree.BTNode().data("d");  
  68.         BTree.BTNode<String> c=new BTree.BTNode().data("c").left(f).right(g);  
  69.         f.parent(c);  
  70.         g.parent(c);  
  71.         BTree.BTNode<String> b=new BTree.BTNode().data("b").left(d).right(e);  
  72.         d.parent(b);  
  73.         e.parent(b);  
  74.         BTree.BTNode<String> a=new BTree.BTNode().data("a").left(b).right(c);  
  75.         b.parent(a);  
  76.         c.parent(a);  
  77.         BTree<String> t=new BTree<String>(a);  
  78.         test(t,c,f);  
  79.     }  
  80.     staticclass BTNode<T>  
  81.     {  
  82.         BTNode<T> left;  
  83.         BTNode<T> right;  
  84.         BTNode<T> parent;  
  85.         T data;  
  86.         public BTNode(){}  
  87.         public BTNode(BTNode<T> l,BTNode<T> r,BTNode<T> p,T d){  
  88.             this.left=l;  
  89.             this.right=r;  
  90.             this.parent=p;  
  91.             this.data=d;  
  92.         }  
  93.         BTNode<T> left(BTNode<T> l){  
  94.             this.left=l;  
  95.             returnthis;  
  96.         }  
  97.         BTNode<T> right(BTNode<T> r){  
  98.             this.right=r;  
  99.             returnthis;  
  100.         }  
  101.         BTNode<T> parent(BTNode<T> p){  
  102.             this.parent=p;  
  103.             returnthis;  
  104.         }  
  105.         BTNode<T> data(T d){  
  106.             this.data=d;  
  107.             returnthis;