二叉搜尋樹和二叉樹的最近公共祖先

凝冰物語發表於2021-05-29

二叉搜尋樹的最近公共祖先

 
對於二叉搜尋樹,設兩個節點的最近公共祖先為節點X,那麼必有X的值介於兩個節點的值之間,而且僅有一個節點滿足條件。
 
基於這個條件,我們可以從根節點開始往下查詢,思路就和二叉搜尋樹查詢節點的思路類似。如果當前節點值比兩個節點都大,則進入左子樹,如果當前節點值比兩個節點都小,則進入右子樹。如果當前節點值介於兩個節點之間,說明找到了最近公共祖先。虛擬碼如下:
 
1 // 預設p的值小於q的值,需要在輸入前調整
2 lowestCommonAncestor(root, p, q)
3     if root.val < p.val and root.val < q.val
4         return lowestCommonAncestor(root.left, p, q)
5     else if root.val > p.val and root.val > q.val
6         return lowestCommonAncestor(root.right, p, q)
7     else
8         return root  

二叉樹的最近公共祖先

對於二叉樹而言,因為沒有節點的值之間的大小關係進行判斷,所以不能選擇只進入一個子樹,需要兩個子樹都進入獲取資訊,然後再進行後續判斷。
 
演算法思路:
假設輸入的兩個節點為p節點和q節點,我們首先判斷根節點是否是輸入的兩個中的一個。如果是的話,肯定就是最近公共祖先節點了,直接返回。如果不是的話,則需要進入兩個子樹查詢。
 
往下查詢的過程中如果當前節點為兩個節點之一,則直接返回。如果不是的話,對左子樹遞迴操作得到返回值為L,對右子樹遞迴操作得到的返回值為R。這裡根據L,R關係返回不同結果。
  如果L和R均不為null,表示左子樹和右子樹都至少存在p和q中的一個,則該節點為最近公共祖先節點,可以返回當前節點
  如果L和R中的一個為null,表示一個子樹至少有p和q中的一個(如果包含兩個,則L和R必是公共祖先)。可以直接返回L或R。
  如果L和R都為null,表示兩顆子樹都沒找到p或q。可以返回null。
  注:這裡返回null的情況表示以當前節點往下查詢,找不到p和q的最近公共父節點,不表示整棵樹中不存在。還要注意root為null時,顯然當前節點往下找沒有結果,可以直接返回null。
 
根據以上思路,可以寫出虛擬碼:
 
 1 lowestCommonAncestor(root, p, q)
 2     // 如果root為null,沒有找的必要,直接返回null
 3     if root = null
 4         return null
 5     // 如果root為其中一個,表示從root出發找到的最近公共祖先節點有的話只可能是root    
 6     if root = p or root = q
 7         return root
 8         
 9     // 對左子樹和右子樹遞迴操作    
10     L <- lowestCommonAncestor(root.left, p, q)
11     R <- lowestCommonAncestor(root.right, p, q)) 
12    
13    // 如果L和R都不為null,表示當前節點就是最近公共祖先節點
14    if L ≠ null and R ≠ null
15        return root
16    else if L = null and R ≠ null
17        return R           // 以root節點往下找,如果有目標節點的話只可能是R
18    else if L ≠ null and R = null
19        return L           // 以root節點往下找,如果有目標節點的話只可能是L 
20    else 
21        return null        // L和R都為null,都沒找到

 

相關文章