1
# Runtime: 1783 ms (Top 30.42%) | Memory: 59.4 MB (Top 95.18%)8
def sumOfDistancesInTree(self, n: int, edges: List[List[int]]) -> List[int]:10
@see https://leetcode.com/problems/sum-of-distances-in-tree/discuss/130583/C%2B%2BJavaPython-Pre-order-and-Post-order-DFS-O(N)15
g = self.create_undirected_graph(17
) # as mentioned in the problem, this graph can be converted into tree19
root = 0 # can be taken to any node between 0 and n - 1 (both exclusive)21
# considering "root" as starting node, we create a tree.23
# tree_nodes[i] = number of nodes in the tree rooted at node i24
# distances[i] = sum of distances of all nodes from ith node to all the25
# other nodes of the tree26
tree_nodes, distances = [0] * n, [0] * n28
def postorder(rt: int, parent: int):30
updating tree_nodes and distances from children of rt. To update them, we must know their31
values at children. And that is why post order traversal is used33
After the traversal is done,34
tree_nodes[rt] = all the nodes in tree rooted at rt35
distances[rt] = sum of distances from rt to all the nodes of tree rooted at rt46
# adding number of nodes in subtree rooted at c to tree rooted at rt47
tree_nodes[rt] += tree_nodes[c]49
# moving to rt from c will increase distances by nodes in tree rooted at c50
distances[rt] += distances[c] + tree_nodes[c]52
def preorder(rt: int, parent: int):54
we start with "root" and update its children.55
distances[root] = sum of distances between root and all the other nodes in tree.57
In this function, we calculate distances[c] with the help of distances[root] and58
that is why preorder traversal is required.67
) + ( # rt -> c increase this much distance68
distances[rt] - tree_nodes[c]69
) # rt -> c decrease this much distance72
postorder(root, ROOT_PARENT)73
preorder(root, ROOT_PARENT)78
def create_undirected_graph(edges: List[List[int]], n: int):82
:return: graph from edges. Note that this undirect graph is a tree. (Any node can be85
g = [[] for _ in range(n)]