0x61 樹的直徑與最近公共祖先(一)

2021-09-24 04:01:44 字數 1010 閱讀 3726

1、樹的直徑:

樹中最遠兩個節點之間的距離為樹的直徑,連線這兩點的路徑被稱為樹的最長鏈。

樹的直徑一般有兩種求法,時間複雜度都是o(n). 我們假設樹以n個點n-1條邊的無向圖形式給出,並儲存在鄰接表(鏈式前向星)中。

演算法1:樹形dp求樹的直徑

不妨設1號節點為根,設d[x]表示從節點x出發向以x為根的子樹,能夠到達的最遠節點的距離。設x的t個子節點為y_1.y_2,....y_t. edge(x, y)表示邊權,顯然有:

d[x] = max(d[y_i] + edge(x, y_i))   1 ≤ i ≤ t

接下來,我們可以考慮對每個節點x求出 "經過節點x的最長鏈的長度" f[x], 整棵樹的直徑為 max,1 ≤ x ≤ n

如何求f[x]呢? 對於x的任意兩個節點y_i和y_j,"經過節點x的最長鏈的長度"可以通過四個部分構成:

1:從y_i到y_i子樹中的最遠距離

2:從y_j到y_j子樹中的最遠距離

3: edge(x, y_i)

4: edge(x, y_j)

不妨設j < i, 也就是說: f[x] = max(d[y_i] + d[y_j] + edge(x, y_i) + edge(x, y_j)  ,1  ≤ j < i ≤ t.

我們沒有必要使用兩個迴圈來計算。思考d[x]的計算過程,在子節點的將要迴圈到i時,d[x]恰好儲存了從節點x出發走向"以y_j(j < i)為根的子樹",能夠到達的最遠節點的距離,這個距離就是d[y_j] + edge(x, y_j), 1 ≤ j < i. 具體看**:

//ans 樹的直徑 

void dp(int x)

}

演算法2:

1、從任意乙個節點出發,通過bfs或dfs遍歷,找到與出發點距離最遠的節點p

2、從p出發,通過dfs或bfs再一次遍歷,找到與p最遠的節點q

從p到q就是樹的一條直徑。

在第二步可以記錄下每個點第一次被訪問時的前驅,最後從q遞迴到p,可以得到直徑的具體方案。

樹的直徑與最近公共祖先

1.1.2 思路 設d x 為從結點x出發走以x為根的子樹,能夠達到最遠結點的距離。設x的子節點為y1,y2,y3.yt,edge x,yi 表示邊的權重,那就有 d x max i i t 接下來設經過x的最長鏈的長度為f x 那麼整棵樹的直徑就是max 1 x n f x 可以由四個部分構成 x...

樹的最近公共祖先

做了一些二叉樹的題,發現二叉樹的查詢問題一般都是從左右子樹遞迴去解決,也往往都能得到答案,因此,這道題可以考慮是否能從左右子樹進行遞迴去解決呢?首先,要想通過遞迴來實現,就需要先確定臨界條件,那麼臨界條件是什麼呢?換句話說,臨界條件就是遞迴中能夠直接返回的特殊情況,第一點則是最常見的 判空 判斷根結...

最近公共祖先 python 二叉樹的最近公共祖先

二叉樹的最近公共祖先 給定乙個二叉樹,找到該樹中兩個指定節點的最近公共祖先。例如,給定如下二叉樹 root 3,5,1,6,2,0,8,null,null,7,4 示例 1 輸入 root 3,5,1,6,2,0,8,null,null,7,4 p 5,q 1 輸出 3 解釋 節點 5 和節點 1 ...