LeetCode

834. 树中距离之和

不会,看不懂官方题解,这是比较容易理解的答案
对于两个相邻节点A和B,将树拆分为两个子树,根节点分别为A和B,A节点到其他所有节点的距离和树形DP - 图1可以分为三部分来计算,第一个是A子树中所有子节点到根节点A的距离和树形DP - 图2,第二个是B子树中所有子节点到另一个根节点B的距离和树形DP - 图3,第三个是B这棵子树中所有节点的数量树形DP - 图4。因此,得出如下两个公式:
树形DP - 图5
因此,可以推出两个相邻节点的解的关系为
树形DP - 图6
只要知道节点0的距离和,那就可以通过DFS或者BFS遍历的方式求出其他节点的距离和。
接下来就是求根节点0的距离和,而各子树的距离和相当于是递归计算。
树形DP - 图7

  1. //距离和
  2. int[] res;
  3. //根节点为0的情况下,各节点的子树中节点数量
  4. int[] cnt;
  5. //图
  6. List<List<Integer>> graph;
  7. int n;
  8. public int[] sumOfDistancesInTree(int N, int[][] edges) {
  9. if (N <= 0) return null;
  10. res = new int[N];
  11. cnt = new int[N];
  12. n = N;
  13. graph = new ArrayList();
  14. //初始化图
  15. for (int i = 0; i < N; i++) {
  16. graph.add(new ArrayList<Integer>());
  17. cnt[i] = 1;
  18. }
  19. for (int[] edge : edges) {
  20. int u = edge[0], v = edge[1];
  21. graph.get(u).add(v);
  22. graph.get(v).add(u);
  23. }
  24. //计算节点0的距离和
  25. dfs(-1, 0);
  26. System.out.println(Arrays.toString(res));
  27. System.out.println(Arrays.toString(cnt));
  28. //dfs反推其他节点的距离和
  29. dfs2(-1, 0);
  30. return res;
  31. }
  32. //计算某个根节点cur的距离和,需要明白根节点一旦确定,整棵树的父子节点关系也就确定了
  33. public void dfs (int parent, int cur) {
  34. List<Integer> childs = graph.get(cur);
  35. for (int i = 0; i < childs.size(); i++) {
  36. if (childs.get(i) == parent) continue;
  37. int child = childs.get(i);
  38. dfs(cur, child);
  39. cnt[cur] += cnt[child];
  40. res[cur] += res[child] + cnt[child];
  41. }
  42. }
  43. public void dfs2 (int parent, int cur) {
  44. List<Integer> childs = graph.get(cur);
  45. for (int i = 0; i < childs.size(); i++) {
  46. if (childs.get(i) == parent) continue;
  47. int child = childs.get(i);
  48. //这里只能是cnt[child],而不能直接使用cnt[cur]
  49. res[child] = res[cur] - cnt[child] + (n - cnt[child]);
  50. dfs2(cur, child);
  51. }
  52. }