Re: [閒聊] 每日LeetCode

作者: Rushia (みけねこ的鼻屎)   2022-12-22 17:59:49
834. Sum of Distances in Tree
給你一個n表示節點數量,和很多個邊表示的一個無向圖,求出一個陣列包含了每個點
到其他所有點的距離和。
Example:
https://assets.leetcode.com/uploads/2021/07/23/lc-sumdist1.jpg
Input: n = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]
Output: [8,12,6,10,10,10]
Explanation: The tree is shown above.
We can see that dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5)
equals 1 + 1 + 2 + 2 + 2 = 8.
Hence, answer[0] = 8, and so on.
思路:
1.最簡單求解的方法就是先建立圖形,接下來對每個點用dfs()求出對其他
點的距離並加總,時間複雜度是 O(n^2) ,測資的n很大所以提交時必然會TLE,我們必
須想辦法優化。
2.對於一個無向圖,我們可以把任意的點當成樹的 root 並讓其他node下垂,這樣看過去
圖形就會是一個m元樹,例如下圖分別以0和2作為root:
https://assets.leetcode.com/uploads/2021/07/23/lc-sumdist1.jpg
0 2
/ \ / | \ \
1 2 或 0 3 4 5
/|\ /
3 4 5 1
3.我們可以先算出以其中一點(這邊用0)到其他所有點的和,以上面的圖片為例子,
定義 f(i) 為從所有點走到 i 點的距離之和,0 到所有點的距離為:
f(0) = 1 + 1 + 2 + 2 + 2 = 8
觀察看看如何以最小成本得到其他點的和,若我們要得到點2的和,他的距離為:
f(2) = 2 + 1 + 1 + 1 + 1 = 6。
4.觀察上面兩式的關係,我們已知點0的和(每一個點的目的地都是0,且0走到0不用動)
,原本每個節點走到 0 需要花費8的距離,當目的地改為 2 之後對於f(2) 來說節點1
需要多走一步,節點0也需要多走一步,而節點3、4、5少走一步,節點2是原點不必走所
以再少走一步,我們可以把 f(2) 表達如下:
f(2) = f(0)(0作為根的和) + 2(點0和1) - 3(點3、4、5) - 1(自己少走一步)
上式可再度簡化:
f(2) = f(0) + 2(節點總數減去「2為root的subtree」數量) - 4(2為root的subtree
節點數量)
= f(0) + N(節點總數) - 2*4 (2為root的subtree節點數量)= 6
我們只需要把一個點作為和的基礎(父節點),並計算要求解的新root的節點數量即可求
和,得出遞迴式:
f(i) = f(i的父節點) + 節點總數 - (2 * i為根的子樹節點數)
5.知道遞迴式之後,按照順序求出:
count[]:每個節點的子節點數量
ans[0]:到節點0的距離和,作為遞迴的初始值
ans[i]:到節點 i 的距離和
6.要求出上面三個遞迴所需的條件,可以用三次dfs求解,因為是無向圖所以要紀錄
走訪了哪些點避免進入死循環,因為這題算是一顆樹所以只需要記錄前個點即可。
JavaCode:
作者: ILoveErr (英梨梨我老婆)   2022-12-22 18:00:00
打那麼長他媽誰看的完
作者: sustainer123 (caster)   2022-12-22 18:02:00
大師
作者: pandix (麵包屌)   2022-12-22 18:03:00
大師

Links booklink

Contact Us: admin [ a t ] ucptt.com