跳到主要内容

LeetCode 834. 树中距离之和

本节目标

先汇总子树规模和距离,再换根计算每个节点的距离和。

题意与约束

给一棵无向树,返回每个节点到所有节点距离的总和。

第一反应与重复子问题

逐点 BFS 会重复经过边。把树先根化后,相邻根的答案只相差子树内外节点各移动一步。

状态定义与转移推导

后序求 size[node] 和根 0 的总距离。换根到子节点时:answer[child] = answer[parent] + n - 2 * size[child]

正确性依据

换根后子树内 size[child] 个节点距离各减一,外部 n-size[child] 个节点各加一,差即为公式。

样例执行过程

官方六节点树先得到根 0 的距离和 8,沿边下传后得到 [8,12,6,10,10,10]

代码实现

C++17
#include <iostream>
#include <vector>
using namespace std;

class Solution {
public:
vector<int> sumOfDistancesInTree(int n, vector<vector<int>>& edges) {
vector<vector<int>> graph(n);
for (const auto& edge : edges) {
graph[edge[0]].push_back(edge[1]);
graph[edge[1]].push_back(edge[0]);
}
vector<int> parent(n, -1);
vector<int> order{0};
vector<int> size(n, 1);
vector<int> answer(n);
for (int index = 0; index < static_cast<int>(order.size()); index++) {
int node = order[index];
for (int nxt : graph[node]) {
if (nxt != parent[node]) {
parent[nxt] = node;
order.push_back(nxt);
}
}
}
for (int index = n - 1; index > 0; index--) {
int node = order[index];
size[parent[node]] += size[node];
answer[0] += size[node];
}
for (int node : order) {
for (int nxt : graph[node]) {
if (parent[nxt] == node) {
answer[nxt] = answer[node] + n - 2 * size[nxt];
}
}
}
return answer;
}
};

复杂度分析

两遍均线性,时间 O(n),邻接表、父序和数组空间 O(n)

边界与易错点

单节点答案为 [0];Python 使用父序正向建树、逆序聚合,避免递归深度风险。

模式迁移

“所有节点作为根”的树题优先寻找从父答案到子答案的增量公式。回到树形动态规划