【问题标题】:Sum of binary tree leaves' values二叉树叶子值的总和
【发布时间】:2019-11-21 12:24:16
【问题描述】:

我写了这段代码,当我使用 print 时,我看到我得到了叶子。然而,函数的最终返回是None,而不是叶子的总和,在这个例子中应该是7。我很高兴知道这里出了什么问题。谢谢!

class Node:
    def __init__(self, val=None):
        self.left = None
        self.right = None
        self.val = val


def sum_leafs(tree):
    if tree is None:
        return 0

    if tree.right and tree.left:
        sum_leafs(tree.right)
        sum_leafs(tree.left)

    elif tree.right or tree.left:
        if tree.right:
            sum_leafs(tree.right)
        elif tree.left:
            sum_leafs(tree.left)

    elif tree.right is None and tree.left is None:
        return sum_leafs(tree.left) + 1


node = Node(10)
node.right = Node(2)
node.left = Node(11)
node.left.right = Node(5)

print(sum_leafs(node))

【问题讨论】:

  • 如果你解决了你的问题,你应该标记正确的答案。

标签: python recursion binary-tree


【解决方案1】:

在对分支(左/右)求和时忘记添加+,并且忘记访问val,这是整个工作最关键的事情。

进一步,逻辑可以简化:

def sum_leafs(tree):
    if tree is None:
        return 0

    if not tree.right and not tree.left:
        return tree.val

    return sum_leafs(tree.right) + sum_leafs(tree.left)

【讨论】:

    【解决方案2】:

    您不是将总和加在一起或返回它们。这也可以通过类中的方法来完成:

    class Node:
        def __init__(self, val=None):
            self.left = None
            self.right = None
            self.val = val
    
        def sum(self):
            s = 0
            if self.left is not None:
                s += self.left.sum()
            if self.right is not None:
                s += self.right.sum()
            return self.val + s
    
    
    node = Node(10)
    node.right = Node(2)
    node.left = Node(11)
    node.left.right = Node(5)
    
    print(node.sum())
    

    返回:

    28
    

    【讨论】:

      【解决方案3】:

      您没有正确返回计算出的叶总和。试试这个:

      class Node:
          def __init__(self, val=None):
              self.left = None
              self.right = None
              self.val = val
      
      
      def sum_leafs(tree):
          if tree is None:
              return 0
      
          elif tree.right and tree.left:
              return sum_leafs(tree.right) + sum_leafs(tree.left)
      
          elif tree.right or tree.left:
              if tree.right:
                  return sum_leafs(tree.right)
              elif tree.left:
                  return sum_leafs(tree.left)
      
          elif tree.right is None and tree.left is None:
              return tree.val
      
      node = Node(10)
      node.right = Node(2)
      node.left = Node(11)
      node.left.right = Node(5)
      
      print(sum_leafs(node))
      
      7
      

      【讨论】:

        【解决方案4】:

        节点

        首先我要更新您的Node 接口,以便在创建节点时可以设置leftright 分支-

        class Node:
          def __init__(self, val=None, left=None, right=None):
            self.left = left
            self.right = right
            self.val = val
        

        这使我们可以更符合人体工程学地创建发束,例如 -

        t = Node(10, Node(11, None, Node(5)), Node(2))
        

        遍历

        现在我们编写一个通用的遍历过程。这使我们能够将 1) 树的遍历与 2) 我们想要对每个树元素执行的预期操作分开 -

        def traverse(tree):
          if tree is None:
            return
          else:
            yield tree.val
            yield from traverse(tree.left)
            yield from traverse(tree.right)
        

        现在对sum_leafs 的需求消失了。我们将遍历逻辑与求和逻辑分离。我们可以通过sumtraverse的简单组合来计算叶子的总和-

        print(sum(traverse(t)))
        # 28
        

        不要重复自己

        或者,我们可以编写一个 search 函数来查找第一个传递谓词的值,而不是对这些值求和 -

        def search(test, tree):
          for val in traverse(tree):
            if test(val):
              return val
        
        print(search(lambda x: x < 10, t))
        # 5
        
        print(search(lambda x: x > 99, t))
        # None
        

        或者,我们可以简单地将每个值收集到一个列表中 -

        print(list(traverse(t)))
        # [ 10, 11, 5, 2 ]
        

        如您所见,从依赖于我们树的每个函数中删除遍历逻辑可能会有很大帮助。


        没有生成器

        如果你不喜欢生成器,你可以编写 traverse 的 Eager 版本,它总是返回 list。现在的区别是没有办法部分遍历树。请注意此程序与生成器版本的相似之处 -

        def traverse(t):
          if t is None:
            return [] # <-- empty
          else:
            return \
              [ t.val
              , *traverse(t.left)  # <-- yield from
              , *traverse(t.right) # <-- yield from
              ]
        
        print(traverse(t))
        # [ 10, 11, 5, 2 ]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-01
          • 2022-01-26
          相关资源
          最近更新 更多