1. 程式人生 > >二叉樹中兩個節點的最低公共父節點

二叉樹中兩個節點的最低公共父節點

問題描述

構建一棵二叉樹(不一定是二叉查詢樹),求出該二叉樹中某兩個結點的最低公共父結點。借用一張圖如下:
這裡寫圖片描述

最低公共父結點的思路

遞迴,首先從樹根開始考慮:

①結點A 和 結點B 要麼都在樹根的左子樹中;②要麼都在樹根的右子樹中;③要麼一個在左子樹中,一個在右子樹中。

這是一個分治演算法,對於情況①和②,可以繼續遞迴分解。對於情況③屬於程式碼第10行判斷,複雜度為O(1)

遞迴表示式可表示為:T(N)=2T(N/2)+O(1),解得T(N)=O(N)

對於③,最低公共父結點為樹根。

對於①,可以進一步判斷,從樹根的左孩子結點考慮:

1)結點A 和 結點B 要麼都在樹根的左子孩子 的 左子樹中;2)要麼都在樹根的左孩子 的 右子樹中;3) 要麼一個在樹根的左孩子的 左子樹中,一個在樹根的左孩子 的 右子樹中。

對於②,可以進一步判斷,從樹根的右孩子的結點考慮:

1)結點A 和 結點B 要麼都在樹根的右子孩子 的 左子樹中;2)要麼都在樹根的右孩子 的 右子樹中;3) 要麼一個在樹根的右孩子的 左子樹中,一個在樹根的右孩子 的 右子樹中。

下面程式碼實現遞迴求解最低公共父結點。

1     /**
 2      * 求解node1 和 node2 的最低公共父結點
 3      * @param node1
 4      * @param node2
 5      * @return 最低公共父結點
 6      */
 7     public BinaryNode<T> commonNode
(BinaryNode<T> node1, BinaryNode<T> node2, BinaryNode<T> root){ 8 if(root == null) 9 return null; 10 if(node1.element == root.element || node2.element == root.element) 11 return root; 12 /* 13 * 若 left==null, node1,node2 都不在 root.left子樹中 14 * 若right==null,node1,node2 都不在root.right子樹中 15 */
16 BinaryNode<T> left = commonNode(node1, node2, root.left); 17 BinaryNode<T> right = commonNode(node1, node2, root.right); 18 19 if(left != null && right != null) 20 return root; 21 return left == null ? right : left; 22 }

根據程式中的第8行和第10行的if語句,可知:

1)若 left==null, 則說明 node1,node2 都不在 root.left子樹中

2)若right==null,則說明 node1,node2 都不在root.right子樹中

3)當對於某個結點,當執行了第16,17行的遞迴後 ,left 和 right 都不為空,說明node1 在 該結點.left子樹中,node2 在 該結點.right子樹中

故第19-20行,返回 該結點 作為公共父結點

例如,求結點8 和 結點5 的最低公共父結點:遞迴呼叫過程如下:

a)commNode(8,5,1)==2

b1)      commNode(8,5,2)==2

c1)             commNode(8,5,4)==8

d1)                      commNode(8,5,8)==8

d2)                     commNode(8,5,9)==null

c2)             commNode(8,5,5)==5

b2)      commNode(8,5,3)==null

a)生成了 b1) b2) 兩個遞迴呼叫,其中 b2)為空,因為結點8,結點5 不在以3為根的子樹中

b1)生成了 c1) c2)兩個遞迴呼叫,其中 c2) 是commNode(8,5,5),根據程式第10行if,返回5,而c1)又生成了 d1) d2)兩個遞迴呼叫

其中,d1) 返回8,d2)返回null, 故執行到第21行語句,return 不空的那個left/right,也就是 d1) 返回的結點8

由於 c1)返回了8, c2)返回了5,都不為空,執行到第19-20行,返回它們的root,即,結點4和結點5的公共父結點:結點2

由於 b1) 生成了 c1) c2) 故 b1) 的值是結點2 又因為 b2) 為null

故 a) 最終是 b1) 的值,即為結點2。