二叉树的直径

时间:2019-03-21 21:38:57

标签: recursion binary-tree tree-traversal postorder

我正在研究一个著名的问题,即二叉树的直径。我知道这里已经对此进行了无数次讨论(Diameter of Binary Tree),但这种解释似乎并不正确。特别是,单个节点树应该返回0,而不是1(我从Leetcode自己的检查器检查了)。无论如何,这是问题陈述:

  

给定一棵二叉树,您需要计算树直径的长度。二叉树的直径是一棵树中任何两个节点之间的最长路径的长度。此路径可能会也可能不会通过根。

enter image description here

答案分别为0、1和5。乍一看,似乎可以计算出左子树的边数和右子树的数目。

所以我从后递归开始(自下而上):

max_diameter = 0
def getDiameter(node):
    if node is NULL:
        return 0 

    left_diameter = getDiameter(node.left)
    right_diameter = getDiameter(node.right)

    max_diameter = max(left + right, max_diameter)

到目前为止,一切都很好。但是代码不起作用,而且我很难理解其中的一些解决方案。例如:

class Solution(object):
    def diameterOfBinaryTree(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.ans = 0

        def depth(p):
            if not p: return 0
            left, right = depth(p.left), depth(p.right)
            self.ans = max(self.ans, left+right)
            return 1 + max(left, right)

        depth(root)
        return self.ans

为什么要比较左子树和右子树?为什么加1?另外,有人说找到高度,有人说找到深度。这很令人困惑,我觉得人们只是在把术语扔掉……任何澄清都是有帮助的。

2 个答案:

答案 0 :(得分:0)

最长的路径总是从一个叶子到一个节点,然后再回到另一个叶子。从节点上看,该路径的长度为左子树的最大深度和右子树的最大深度之和。

我们不能仅将其应用于根节点,因为您的第三个示例显示了该节点可能在树中的任何位置。因此,您必须测试所有节点并获得最大的解决方案:

diameter (Leaf)     = 0
diameter (Node l r) = max(diameter l, diameter r, depth l + depth r)

depth (Leaf)     = 0
depth (Node l r) = 1 + max(depth l, depth r)

您找到的解决方案以递归方式计算所有节点上的深度,并同时更新self.ans插槽中的最大直径。

答案 1 :(得分:0)

在每个节点上,您都需要知道孩子的深度,才能据此计算树的直径,直径基本上是您从左孩子中最深的节点到右孩子中最深节点的距离。

关于您的第二个代码(此问题的解决方案),我们正在计算每个节点的深度,同时跟踪到目前为止在每个探索的节点上我们看到的最长路径。 这是它的一些评论风格:

def diameterOfBinaryTree(self, root):

    self.longest = 0

    def depth(node):

        if not node:
            return 0

        left_depth = depth(node.left)
        right_depth = depth(node.right)

        # A path is longest if we add depths from both sides
        # Overall Longest is maximum of what we have seen so far and this path
        self.longest = max(self.longest, left_depth+right_depth)

        # Depth at this node is maximum of either of our children +1 (our own node)
        return max(left_depth, right_depth) + 1

    # Calculating depth, meanwhile tracking the longest path in self.longest
    depth(root)

    return self.longest