【问题标题】:Find the root-to-leaf path with the max sum - can't compare issues找到具有最大总和的从根到叶的路径 - 无法比较问题
【发布时间】:2021-01-11 22:24:50
【问题描述】:

我现在正在寻找总和最大的从根到叶的路径。我的做法是:

def max_sum(root):
    _max = 0
    find_max(root, _max, 0)
    return _max

def find_max(node, max_sum, current_sum):
    if not node:
        return 0
    current_sum += node.value
    if not node.left and not node.right:
        print(current_sum, max_sum, current_sum > max_sum)
        max_sum = max(max_sum, current_sum)
    if node.left:
        find_max(node.left, max_sum, current_sum)
    if node.right:
        find_max(node.right, max_sum, current_sum)
    current_sum -= node.value

class TreeNode():
    def __init__(self, _value):
        self.value = _value
        self.left, self.right, self.next = None, None, None

def main():
    root = TreeNode(1)
    root.left = TreeNode(7)
    root.right = TreeNode(9)
    root.left.left = TreeNode(4)
    root.left.right = TreeNode(5)
    root.right.left = TreeNode(2)
    root.right.right = TreeNode(7)

    print(max_sum(root))

    root = TreeNode(12)
    root.left = TreeNode(7)
    root.right = TreeNode(1)
    root.left.left = TreeNode(4)
    root.right.left = TreeNode(10)
    root.right.right = TreeNode(5)

    print(max_sum(root))

main()

有输出:

12 0 True
13 0 True
12 0 True
17 0 True
0
23 0 True
23 0 True
18 0 True
0

Process finished with exit code 0

预期的输出是 17 和 23。

我想确认一下为什么我的方法无法比较max_sumcurrent_sum?即使它在比较中返回 true,但不会更新 max_sum。感谢您的帮助。

【问题讨论】:

  • 没有详细查看您的代码,但是拥有一个函数和另一个同名变量是个坏主意
  • max_sum 中,_max 被设置为 0,然后从不改变。因此,返回 0。
  • 谢谢,@turtle。我不确定哪个变量名与函数名冲突?
  • 谢谢@mkrieger1。你介意解释更多吗?我虽然我的代码将更新find_max 函数中的_max
  • @QiangSuper:我的意思是max_sum。同样正如其他人指出的那样,问题在于max_sum 内部的变量find_max 仅对该函数是本地的。更新它的值不会改变_max的值

标签: python binary sum max


【解决方案1】:

错误修复

这是我们可以修复您的 find_sum 函数的方法 -

def find_max(node, current_sum = 0):
  # empty tree
  if not node:
      return current_sum

  # branch
  elif node.left or node.right:
    next_sum = current_sum + node.value
    left = find_max(node.left, next_sum)
    right = find_max(node.right, next_sum)
    return max(left, right)
  
  # leaf
  else:
    return current_sum + node.value
t1 = TreeNode \
  ( 1
  , TreeNode(7, TreeNode(4), TreeNode(5))
  , TreeNode(9, TreeNode(2), TreeNode(7))
  )
  
t2 = TreeNode \
  ( 12
  , TreeNode(7, TreeNode(4), None)
  , TreeNode(1, TreeNode(10), TreeNode(5))
  )

print(find_max(t1))
print(find_max(t2))  
17
23

查看过程

我们可以通过跟踪其中一个例子来可视化计算过程,find_max(t2) -

             12
          /       \
         7         1
        / \       / \
       4   None  10  5
     find_max(12,0)
          /      \
         7        1
        / \      / \
       4  None  10  5
          find_max(12,0)
          /           \
max(find_max(7,12), find_max(1,12))
     / \                / \
    4  None           10   5
                                find_max(12,0)
                           /                         \
         max(find_max(7,12),                          find_max(1,12))
            /              \                          /             \
max(find_max(4,19), find_max(None,19))  max(find_max(10,13), find_max(5,13))
                        find_max(12,0)
                       /              \     
     max(find_max(7,12),              find_max(1,12))
      /              \                /             \
 max(23,             19)         max(23,            18)
                        find_max(12,0)
                       /              \     
     max(find_max(7,12),              find_max(1,12))
            |                                |
           23                               23
            find_max(12,0)
            /            \     
     max(23,              23)  
            find_max(12,0)
                 |
                23
23

改进

但是我认为我们可以改进。就像我们在您的 previous question 中所做的那样,我们可以再次使用数学归纳法 -

  1. 如果输入树t为空,返回空结果
  2. (感应)t 不为空。如果存在子问题t.leftt.right 分支,则将t.value 添加到累积结果r 并在每个分支上重复
  3. (感应)t 不为空且t.leftt.right 均为空;已到达叶节点;将t.value 添加到累加结果r 并得出总和
def sum_branch (t, r = 0):
  if not t:
    return                                       # (1)
  elif t.left or t.right:
    yield from sum_branch(t.left, r + t.value)   # (2)
    yield from sum_branch(t.right, r + t.value)
  else:
    yield r + t.value                            # (3)
t1 = TreeNode \
  ( 1
  , TreeNode(7, TreeNode(4), TreeNode(5))
  , TreeNode(9, TreeNode(2), TreeNode(7))
  )
  
t2 = TreeNode \
  ( 12
  , TreeNode(7, TreeNode(4), None)
  , TreeNode(1, TreeNode(10), TreeNode(5))
  )

print(max(sum_branch(t1)))
print(max(sum_branch(t2)))
17
23

泛型

也许写这个问题更有趣的方法是先写一个通用的paths函数-

def paths (t, p = []):
  if not t:
    return                                     # (1)
  elif t.left or t.right:
    yield from paths(t.left, [*p, t.value])    # (2)
    yield from paths(t.right, [*p, t.value])
  else:
    yield [*p, t.value]                        # (3)

然后我们可以将最大和问题解决为泛型函数maxsumpaths 的组合-

print(max(sum(x) for x in paths(t1)))
print(max(sum(x) for x in paths(t2)))
17
23

【讨论】:

  • 感谢您的帮助。你介意看看我的代码吗?我担心的是为什么 max_sum 没有被声明 max_sum = max(max_sum, current_sum) 更新?
  • 问题在于find_max(node.left, max_sum, current_sum)find_max(node.right, max_sum, current_sum),我们不使用这些调用的返回值。 max_sum 也是按值传递的,而不是按引用传递的。在您的另一个问题中,此技术有效,因为 [] 是通过引用传递的。我用find_sum 的编辑更新了我的答案的顶部。这有帮助吗?
  • 感谢您的帮助。我想我已经非常接近最终答案了。但我还是有点困惑。假设我们在平衡树的叶子上,此时,max_sum 仍然为 0,因为尚未更新。由于max_sum 仅将其值传递给函数,所有叶节点都会将其current_summax_sum = 0 进行比较?如果是,返回的max_sum怎么还是0?
  • 我还有一个问题。在您的方法中,您返回max(left, right)。所以递归的逻辑是这样的:在叶子节点,找出final_sum,然后回到内部节点,比较具有相同父节点的子节点。最终,在根节点比较这些父节点,这就是我们的结果。
  • 感谢您的时间和耐心。
猜你喜欢
  • 1970-01-01
  • 2023-03-12
  • 2016-08-03
  • 2022-11-04
  • 2014-02-05
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
相关资源
最近更新 更多