二叉搜尋樹的最近公共祖先
對於二叉搜尋樹,設兩個節點的最近公共祖先為節點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,都沒找到