Sum of Distances in a Tree

Rerooting — first DFS computes subtree sums; second DFS shifts the perspective using the edge swing formula.

Hard
Time O(n) Space O(n)
LeetCode
5 min read
tree dfs rerooting

Problem#

Given a tree with n nodes and n - 1 edges, return an array where ans[i] is the sum of distances from node i to every other node.

Examples#

  • n = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]][8,12,6,10,10,10]
  • n = 1, edges = [][0]
  • n = 2, edges = [[1,0]][1,1]

Constraints#

  • 1 <= n <= 3 * 10^4.

Approach#

Rerooting DP. First DFS from 0: count[u] = subtree size; dist[0] = sum of distances from 0. Second DFS: for each child v of u, dist[v] = dist[u] - count[v] + (n - count[v]) because moving the root from u to v brings count[v] nodes one step closer and pushes n - count[v] nodes one step further.

Solution#

Sum of Distances in a Tree
class Solution {
public:
vector<int> sumOfDistancesInTree(int n, vector<vector<int>>& edges) {
vector<vector<int>> adj(n);
for (auto& e : edges) {
adj[e[0]].push_back(e[1]);
adj[e[1]].push_back(e[0]);
}
vector<int> count(n, 1), ans(n, 0);
function<void(int,int,int)> dfs1 = [&](int u, int parent, int depth) {
ans[0] += depth;
for (int v : adj[u]) {
if (v == parent) continue;
dfs1(v, u, depth + 1);
count[u] += count[v];
}
};
dfs1(0, -1, 0);
function<void(int,int)> dfs2 = [&](int u, int parent) {
for (int v : adj[u]) {
if (v == parent) continue;
ans[v] = ans[u] - count[v] + (n - count[v]);
dfs2(v, u);
}
};
dfs2(0, -1);
return ans;
}
};

Editorial#

Rerooting is the standard technique to compute per-node aggregates on trees in O(n). The edge-swing formula expresses the answer at a new root in O(1) given the old root’s answer plus subtree counts.

Complexity#

  • Time: O(n).
  • Space: O(n).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.