这是一道非常经典的 树形 DP + 换根 DP 难题,我直接给你 可提交的 Java 标准解法,思路清晰、一遍 AC。

题目思路

1. 先建图(树),用邻接表。
2. 第一次 DFS(后序):

  • 计算以  0  为根时,每个子树的节点数  count[]
  • 计算根到所有节点的距离和  res[0] 
    3. 第二次 DFS(前序/换根):
  • 从父节点推子节点:
     res[child] = res[parent] - count[child] + (n - count[child])

Java 完整代码

java

import java.util.*;

class Solution {
List<List> graph;
int[] res;
int[] count;
int n;

public int[] sumOfDistancesInTree(int n, int[][] edges) {
    this.n = n;
    graph = new ArrayList<>();
    for (int i = 0; i < n; i++) {
        graph.add(new ArrayList<>());
    }
    for (int[] e : edges) {
        int u = e[0], v = e[1];
        graph.get(u).add(v);
        graph.get(v).add(u);
    }

    res = new int[n];
    count = new int[n];
    Arrays.fill(count, 1);

    // 第一次 DFS:以 0 为根,求 count 和 res[0]
    dfs1(0, -1);
    // 第二次 DFS:换根 DP
    dfs2(0, -1);

    return res;
}

// 后序:求子树大小 & 根 0 的总距离
void dfs1(int u, int parent) {
    for (int v : graph.get(u)) {
        if (v == parent) continue;
        dfs1(v, u);
        count[u] += count[v];
        res[u] += res[v] + count[v];
    }
}

// 前序:换根推导
void dfs2(int u, int parent) {
    for (int v : graph.get(u)) {
        if (v == parent) continue;
        res[v] = res[u] - count[v] + (n - count[v]);
        dfs2(v, u);
    }
}

}

核心公式(一定要背)

从父 u → 子 v:

  • 靠近 v 的 count[v] 个点 距离 -1
  • 远离 v 的 n - count[v] 个点 距离 +1

所以:

res[v] = res[u] - count[v] + (n - count[v])

如果你需要,我可以再给你:

  • 逐行注释版
  • 手算模拟过程
  • Python / C++ 版本
    你想要哪个?
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐