为以下问题写了一个不必要的复杂解决方案:
给定二叉树和求和,确定树是否有 root-to-leaf路径,以便沿路径添加所有值 等于给定的总和。
无论如何,我试图调试这里出了什么问题。我使用了一个命名元组,这样我就可以跟踪数字是否已找到以及运行总和,但看起来运行总和从不增加到零以上。但是,在任何给定的叶节点处,运行总和将是叶节点的值,并且在下一次迭代中,运行总和应该增加当前运行总和。任何人都知道我的#39;信仰的递归跳跃有什么不对。这里?
def root_to_leaf(target_sum, tree):
NodeData = collections.namedtuple('NodeData', ['running_sum', 'num_found'])
def root_to_leaf_helper(node, node_data):
if not node:
return NodeData(0, False)
if node_data.num_found:
return NodeData(target_sum, True)
left_check = root_to_leaf_helper(node.left, node_data)
if left_check.num_found:
return NodeData(target_sum, True)
right_check = root_to_leaf_helper(node.right, node_data)
if right_check.num_found:
return NodeData(target_sum, True)
new_running_sum = node.val + node_data.running_sum
return NodeData(new_running_sum, new_running_sum == target_sum)
return root_to_leaf_helper(tree, NodeData(0, False)).num_found
编辑:我意识到这实际上只是检查是否有任何路径(不是以叶子结尾)具有正确的值,但我的问题仍然在于理解为什么运行总和没有正确递增。
答案 0 :(得分:0)
您可以将路径的运行列表作为递归函数/方法的签名的一部分,并使用生成器在左右节点上调用函数/方法。生成器将使您能够找到从起始节点延伸的路径。为简单起见,我将解决方案实现为类方法:
class Tree:
def __init__(self, *args):
self.__dict__ = dict(zip(['value', 'left', 'right'], args))
def get_sums(self, current = []):
if self.left is None:
yield current + [self.value]
else:
yield from self.left.get_sums(current+[self.value])
if self.right is None:
yield current+[self.value]
else:
yield from self.right.get_sums(current+[self.value])
tree = Tree(4, Tree(10, Tree(4, Tree(7, None, None), Tree(6, None, None)), Tree(12, None, None)), Tree(5, Tree(6, None, Tree(11, None, None)), None))
paths = list(tree.get_sums())
new_paths = [a for i, a in enumerate(paths) if a not in paths[:i]]
final_path = [i for i in paths if sum(i) == 15]
输出:
[[4, 5, 6]]
答案 1 :(得分:0)
我认为你需要清楚地思考信息是从树上流下来的(从根到叶)还是在树上(从叶到根)。看起来node_data
的{{1}}参数在树的顶部(根)初始化,然后通过递归调用向下传递到每个节点。这很好,但就我所知,它在树下的路上从未改变过。它只是没有受到影响。因此,root_to_leaf_helper
的第一次检查将始终为假。
更糟糕的是,由于node_data.num_found
在树下的路上始终是相同的(node_data
),因此下一行尝试将当前节点的值添加到运行总和中:
(0, False)
将始终将new_running_sum = node.val + node_data.running_sum
添加到0,因为node.val
始终为0。
希望这很清楚,我意识到这有点难以解释。
但是试图非常清楚地思考流向树的信息(在递归调用的参数中)与流向树的信息(在递归调用的返回值中)将使这更加清晰。