There is an undirected connected tree with n nodes labeled from 0 to n - 1 and n - 1 edges.
You are given the integer n and the array edges where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the tree.
Return an array answer of length n where answer[i] is the sum of the distances between the ith node in the tree and all other nodes.
Example 1:
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.
Example 2:
Input: n = 1, edges = []
Output: [0]
Example 3:
Input: n = 2, edges = [[1,0]]
Output: [1,1]
Constraints:
1 <= n <= 3 * 104
edges.length == n - 1
edges[i].length == 2
0 <= ai, bi < n
ai != bi
The given input represents a valid tree.
Solutions
Solution 1: Tree DP (Re-rooting)
Thinking
We need the sum of distances from every node. \(n\le 3\cdot 10^4\), so a DFS from each root is quadratic. After rerooting, neighboring answers differ only by subtree size versus the rest of the tree.
Root at \(0\) to get \(ans[0]\) and subtree sizes, then a second DFS pushes \(t-\textit{size}[j]+n-\textit{size}[j]\) to each child. Two traversals fill every answer.
First, we run a DFS to calculate the size of each node's subtree, recorded in the array \(size\), and compute the sum of distances from node \(0\) to all other nodes, recorded in \(ans[0]\).
Next, we run another DFS to enumerate the sum of distances from each node when it is considered as the root. Suppose the answer for the current node \(i\) is \(t\). When we move from node \(i\) to node \(j\), the sum of distances changes to \(t - size[j] + n - size[j]\), meaning the sum of distances to node \(j\) and its subtree nodes decreases by \(size[j]\), while the sum of distances to other nodes increases by \(n - size[j]\).
The time complexity is \(O(n)\), and the space complexity is \(O(n)\), where \(n\) is the number of nodes in the tree.
We need the sum of distances from every node. With \(n\le 3\cdot 10^4\), a walk from each root is quadratic. After rerooting, neighboring answers differ only by subtree size versus the rest of the tree. Recursion along a chain uses a call depth equal to \(n\) and overflows Python once the chain reaches length \(1000\). Subtree sizes are known only after the children finish, so the first walk is a post-order stack: state \(0\) adds the depth and pushes the children, and state \(1\) totals \(size\). The second answer depends only on the parent's answer and the finished sizes, so a pre-order stack passes \(t-size[j]+n-size[j]\) to each child.
Root the tree at \(0\) and walk in post-order. The stack holds a node, its parent, a depth, and a state. In state \(0\), add the depth to \(ans[0]\), push the same node with state \(1\), and push every child. In state \(1\), every child size is already stored, and \(size[i]\) is \(1\) plus those sizes.
Then reroot with an explicit stack. It starts with \((0,-1,ans[0])\). When node \(i\) is popped, write the current sum \(t\) into \(ans[i]\). Moving from \(i\) to a child \(j\) decreases the distances inside \(j\)'s subtree by \(size[j]\) and increases the distances to every other node by \(n-size[j]\), so the pushed sum is \(t-size[j]+n-size[j]\).
The time complexity is \(O(n)\), and the space complexity is \(O(n)\), where \(n\) is the number of nodes in the tree.