最低公共祖先

2021-06-28 06:27:06 字數 1565 閱讀 5305

二叉樹結點的定義如下:

[cpp]view plain

copy

struct

node ;  

給定二叉樹中的兩個結點,輸出這兩個結點的最低公共祖先結點(lca)。注意,該二叉樹不一定是二叉搜尋樹。

比如給定的二叉樹如下所示,則可以知道結點1和5的最低公共祖先結點為5,結點4和5的最低公共祖先結點為5。

_______3______

/ \

___5__ ___1__

/ \ / \

6 _2 0 8

/ \

7 4

我們可以從根結點出發,判斷當前結點的左右子樹是否包含這兩個結點。如果左子樹包含兩個結點,則它們的最低公共祖先結點也一定在左子樹中。如果右子樹包含兩個結點,則它們的最低公共祖先結點也一定在右子樹中。如果乙個結點在左子樹,而另乙個結點在右子樹中,則當前結點就是它們的最低公共祖先結點。根據該思路寫出**如下,注意這裡已經假定p和q是二叉樹中的結點。

[cpp]view plain

copy

/*查詢二叉樹中兩個結點最低公共祖先結點*/

struct

node* lca(

struct

node *root, 

struct

node *p, 

struct

node *q)   

/*判斷root為根的樹是否包含結點p*/

bool

hasnode(

struct

node* root, 

struct

node* p)    

由於我們對每個結點都呼叫了hasnode函式,而該函式類似於遍歷二叉樹,複雜度為o(n),所以總的時間複雜度為o(n^2),我們期望找到乙個更好的方法。

由於自頂向下的方法需要重複遍歷結點,使用自底向上的方法可以避免這種情況。

自底向上遍歷結點,一旦遇到結點等於p或者q,則將其向上傳遞給它的父結點。父結點會判斷它的左右子樹是否都包含其中乙個結點,如果是,則父結點一定是這兩個節點p和q的lca,傳遞父結點到root。如果不是,我們向上傳遞其中的包含結點p或者q的子結點,或者null(如果子結點不包含任何乙個)。該方法時間複雜度為o(n)。

[cpp]view plain

copy

typedef

struct

node node;  

node *lca(node *root, node *p, node *q)   

還有乙個方法就是依次得到從根結點到結點p和q的路徑,找出它們路徑中的最後乙個公共結點即是它們的lca。該演算法在何海濤先生的部落格中有詳細描述,這裡就不贅述,詳見該方法複雜度也為o(n),不過需要額外的空間儲存路徑,當然第2種方法中遞迴也是需要棧空間的,不過整體來看第2種方法簡潔但是不是很好理解,而公共路徑法則更加易懂。

最低公共祖先

對於樹中兩個節點而言,最低公共祖先lca其實就是該節點左邊和右邊分別包含a,b兩個節點。只有a,b分別在其左右子樹中。首先判斷該節點是否非空,空返回null,表示既沒有a,有沒有b 如果該節點本身是a,或者b中的乙個則返回該節點 遞迴的判斷該節點的左右子樹,如果左右子樹都不是返回null,說明左右子...

Tree 最低公共祖先系列

原題目 在bst中的特殊形式使得假如出現了乙個數比其中乙個小,比另乙個大就是復合題意了。不可能出現還有另外的情況。public treenode lowestcommonancestor treenode node,treenode p,treenode q else if root.val p.v...

最低公共祖先問題 鍊錶 樹

兩個鍊錶的第乙個公共節點 可以利用兩個輔助棧實現,也 可以遍歷鍊錶兩次,求節點個數差,長的鍊錶先遍歷,然後同時開始遍歷,找到相同節點 struct listnode listnode firstpublicnode listnode phead1,listnode phead2 while pnod...