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