樹的最低公共祖先和主方法

2021-09-06 13:32:53 字數 1768 閱讀 1935

lca 分為幾種情況

1. binary search tree 的 lca

2. binary tree with parent pointer

3. binary tree without parent pointer

4. ordinary tree without parent pointer

binary search tree

思路1. 對乙個節點 node, 假如 n1,n2 均大/小於 node->val, 那麼lca一定在 node->right 分支上

2. 若乙個大於乙個小於, 則 lca 就是 node 本身

3. updown 解法, log(n) 的時間複雜度

binary tree with parent pointer

思路1. 先 find 到兩個節點, 並記錄深度

2. 較深的節點先走深度之差步, 然後兩個節點同時向上走,直到相遇

3. 上面幾乎就是求解鍊錶的公共節點問題了, 時間複雜度為 o(n), 空間複雜度為常數

binary tree without parent pointer

top-down 解法 worst case, 時間複雜度為 o(n^2)

1. 從 root 開始, 對每乙個節點 node 作檢測, 若 node 等於兩個節點之一, 而返回 node

2. 否則, 檢測 node->left 中, 有幾個待求 lca 節點存在(0?1?2?), 若 0,2 則直接到另一側子樹中去尋找

3. 若為 1, 則說明兩個節點在 node 兩側, 返回 node 即可

在樹是平衡樹時, 每次減半, 時間複雜度計算方法如下:

時間複雜度的計算方法

t(n) = t(n/2) + n/2

a = 1, b = 2, f(n) = n

根據主定理, 時間複雜度為 o(n*logn)

若樹是 degenerate 的, 時間複雜度為 o(n^2)

bottom-up 解法 時間複雜度為 o(n)

上面解法的問題在於重複計算, 而 bottom-up 則致力於解決重複計算

從下到上遍歷, 一旦遇到兩個節點中的乙個, 則將該節點傳遞到其父親, 直到兩個節點相遇, 返回即可

思路有些抽象, **卻很簡潔

update 2023年2月24日12:00:56

這實際上就是後序遍歷, root 訪問之前, 其左右孩子都已被訪問過了. **的框架和求 depth 一致

node *lca(node *root, node *p, node *q)
leetcode 上有完整的描述 

一般樹的 lca

使用 dfs 定位兩個節點的位置, 並儲存路徑, 然後求兩個鍊錶的公共祖先

主方法

為如下形式的遞迴式提供了一種「菜譜」式的求解方法,如下所示

其中a≥1和b>1是常數,f(n)是漸近正函式。為了使用主方法,需要牢記三種情況,但隨後你就可以很容易地求解很多遞迴式,通常不需要紙和筆的幫助。

主方法依賴於下面的定理。

定理4.1(主定理)    令a≥1和b>1是常數,f(n)是乙個函式,t(n)是定義在非負整數上的遞迴式:

那麼t(n)有如下漸近界:

主定理不能適合於這樣的遞迴式:t(n)=2t(n/2)+nlgn,因為該遞迴式落入了情況2和情況3之間的間隙。利用主定理計算遞迴式非常方便,不用再畫遞迴樹了。

最低公共祖先問題 鍊錶 樹

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

235 二叉樹最低公共祖先

給定乙個二叉搜尋樹,找到該樹中兩個指定節點的最近公共祖先。最近公共祖先的定義為 對於有根樹 t 的兩個結點 p q,最近公共祖先表示為乙個結點 x,滿足 x 是 p q 的祖先且 x 的深度盡可能大 乙個節點也可以是它自己的祖先 例如,給定如下二叉搜尋樹 root 6,2,8,0,4,7,9,nul...

樹中兩結點的最低公共祖先(C 實現)

題目是,輸入兩個樹結點,求它們的最低公共祖先 首先,要說明的是,這是一組題目,根據劍指offer上所講的,這道題可能會分好幾種情況,因此,如果在面試時候遇到,我們需要和面試官溝通,而不是一上來就寫 二叉搜尋樹 又叫二叉排序樹 中序遍歷是可以得到有序序列的,因此,我們可以利用這個性質來解題。假設給定的...