2012-04-04 80 views

回答

4

如果節點「知道」它們的深度 - 或者您願意允許空間計算節點的深度,那麼您可以返回從較低節點到較高節點的相同深度,然後一次上升一層直到它們相遇。

取決於在這種情況下「額外空間」的含義。你可以用一個整數來完成 - 兩個節點的深度差異。那太多了嗎?

另一種可能性是您沒有父指針,您可以使用指針反轉 - 每次遍歷指針時,請記住您來自的位置,請記住您將在下一次遍歷的指針,然後在之前下一個指針遍歷,將該指針替換爲後指針。在樹上恢復時,必須將其撤消。這將一個指針的空間作爲臨時的。另一個整數可以保持深度,因爲你一直在努力工作。爲所尋找的兩個節點同步執行此操作,以便您可以從較低的那個節點繼續工作,直到兩次遍歷中的高度相同,然後從兩個節點恢復工作,直到處於共同節點。這需要三個額外的內存 - 一個用於當前深度,一個用於在指針反轉期間使用的臨時內存。非常節省空間。這值得麼?

+0

我沒有父指針,無論我在節點中的景深。 – Peter 2012-04-04 14:03:22

+0

所以你有一個nary搜索樹,而不僅僅是一棵nary樹?否則你無法知道構建字符串的路徑。當你按照自己的方式工作時,你可以計算深度。但是,如果沒有父指針,您可以在遍歷時選擇反轉指針,或者遵循wildplasser提供的方法。 – DRVic 2012-04-04 15:51:42

+0

我可以通過深度優先遍歷,我可以從兩個獨立的字符串保存從根到兩個節點的路徑,然後採取普通前綴的最後一個字符。這將是答案,但在這裏我使用兩個字符串,即額外的空間。 – Peter 2012-04-04 15:53:46

0

對兩個節點進行同步步行。

  • 從LCA = root開始;
  • 循環:
  • 找到步驟採取A和對於B
  • 步驟,如果這些是等於{LCA =步驟; decend A;下降B;轉到循環; }
  • 完成:LCA現在包含A用LCA和B

僞碼C:

struct node { 
     struct node *offspring[1234]; 
     int payload; 
     }; 

     /* compare function returning the slot in which this should be found/placed */ 
int find_index (struct node *par, struct node *this); 

struct node *lca(struct node *root, struct node *one, struct node *two) 
{ 
struct node *lca; 
int idx1,idx2; 

for (lca=root; lca; lca=lca->offspring[idx1]) { 
    idx1 = find_index(lca, one); 
    idx2 = find_index(lca, two); 
    if (idx1 != idx2 || idx1 < 0) break; 
    if (lca->offspring[idx1] == NULL) break; 
    } 
return lca; 
} 
+0

這個假設find_index can無需構建預訂遍歷即可實現。如果這不是一棵搜索樹,而只是一棵樹,這是如何完成的? – DRVic 2012-04-04 13:47:09

+0

那麼,恕我直言,這基本上是相同的問題,你建立兩個字符串組成的路徑A和B.你是如何獲得字符串,如果樹不可搜索? – wildplasser 2012-04-04 13:52:45

+0

給定節點,您可以將路徑返回到根目錄,並在每個步驟之前預先等待字符串。這是標記算法,沒有語言,所以我假定邊緣可以在任一方向上遍歷。 – DRVic 2012-04-04 15:48:32

2

回去做了一個二叉樹。如果你可以做一個二叉樹,你可以做一個n-ary樹。

這裏的a link to LCA in a binary tree

而這裏的將其轉換爲n元樹LCA後,它的外觀:

public class LCA { 

    public static <V> Node<V> 
       lowestCommonAncestor(Node<V> argRoot, Node<V> a, Node<V> b) { 

     if (argRoot == null) { 
     return null; 
     } 

     if (argRoot.equals(a) || argRoot.equals(b)) { 
     // if at least one matched, no need to continue 
     // this is the LCA for this root 
     return argRoot; 
     } 

     Iterator<Node<V>> it = argRoot.childIterator(); 
     // nr of branches that a or b are on, 
     // could be max 2 (considering unique nodes) 
     int i = 0; 
     Node<V> lastFoundLCA = null; 
     while (it.hasNext()) { 
     Node<V> node = lowestCommonAncestor(it.next(), a, b); 
     if (node != null) { 
      lastFoundLCA = node; 
      i++ ; 
     } 
     if (i >= 2) { 
      return argRoot; 
     } 
     } 

     return lastFoundLCA; 
    } 

    } 
+0

偉大的修改。但是這個解決方案假定樹中都存在兩個節點,如果情況並非如此,那麼在某些情況下它會失敗。 – yusong 2017-03-21 21:06:07

相關問題