Я предлагаю вам постфиксный DFS.Для каждого узла сохраните ссылку своего предшественника.
-
sum_by_rank
для листа - это пустой dict; sum_by_rank
для любого узла - это dict ranks of all subnodes -> values of all subodes
.Если два или более подузлов имеют одинаковый ранг, просто добавьте их значения.
Постфиксный DFS позволяет вычислять суммы снизу вверх.
Вот некоторая программа на Python 3.7 дляиграть с (код, вероятно, не оптимизирован):
from dataclasses import dataclass
from typing import List, Dict
@dataclass
class Node:
value: int
rank: int
sum_by_rank: Dict[int, int]
children: List[object]
tree = Node(5, 0, {}, [
Node(4,2, {}, [Node(3,1, {}, [])]),
Node(7,2, {}, [Node(11,1, {}, [Node(7,8, {}, [])])]),
Node(8,4, {}, [Node(3,3, {}, []), Node(9,5, {}, []), Node(4,2, {}, [])]),
])
def dfs(node, previous=None):
for child in node.children:
dfs(child, node)
node.sum_by_rank[child.rank] = node.sum_by_rank.get(child.rank, 0) + child.value # add this children rank -> value
# add the subtree rank -> value
for r,v in child.sum_by_rank.items():
node.sum_by_rank[r] = node.sum_by_rank.get(r, 0)+v
dfs(tree)
print (tree)
# Node(value=5, rank=0, sum_by_rank={2: 15, 1: 14, 8: 7, 4: 8, 3: 3, 5: 9}, children=[Node(value=4, rank=2, sum_by_rank={1: 3}, children=[Node(value=3, rank=1, sum_by_rank={}, children=[])]), Node(value=7, rank=2, sum_by_rank={1: 11, 8: 7}, children=[Node(value=11, rank=1, sum_by_rank={8: 7}, children=[Node(value=7, rank=8, sum_by_rank={}, children=[])])]), Node(value=8, rank=4, sum_by_rank={3: 3, 5: 9, 2: 4}, children=[Node(value=3, rank=3, sum_by_rank={}, children=[]), Node(value=9, rank=5, sum_by_rank={}, children=[]), Node(value=4, rank=2, sum_by_rank={}, children=[])])])
Следовательно, чтобы получить sum
узла, просто добавьте значения, связанные с рангами, большими или равными рангу узла.В Python:
sum(value for rank, value in node.sum_by_rank.items() where rank >= node.rank)