我正在研究一个著名的问题,即二叉树的直径。我知道这里已经对此进行了无数次讨论(Diameter of Binary Tree),但这种解释似乎并不正确。特别是,单个节点树应该返回0,而不是1(我从Leetcode自己的检查器检查了)。无论如何,这是问题陈述:
给定一棵二叉树,您需要计算树直径的长度。二叉树的直径是一棵树中任何两个节点之间的最长路径的长度。此路径可能会也可能不会通过根。
答案分别为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?另外,有人说找到高度,有人说找到深度。这很令人困惑,我觉得人们只是在把术语扔掉……任何澄清都是有帮助的。
答案 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