543.二叉树的直径
题目描述
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
示例 :
给定二叉树
1
/ \
2 3
/ \
4 5
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
注意:两结点之间的路径长度是以它们之间边的数目表示。
思路
- 深度优先搜索
首先我们知道一条路径的长度为该路径经过的节点数减一,所以求直径(即求路径长度的最大值)等效于求路径经过节点数的最大值减一。
而任意一条路径均可以被看作由某个节点为起点,从其左儿子和右儿子向下遍历的路径拼接得到。
假设我们知道对于该节点的左儿子向下遍历经过最多的节点数 LLL (即以左儿子为根的子树的深度) 和其右儿子向下遍历经过最多的节点数 RRR (即以右儿子为根的子树的深度),那么以该节点为起点的路径经过节点数的最大值即为 L+R+1L+R+1L+R+1 。
我们记节点 node 为起点的路径经过节点数的最大值为 dnode ,那么二叉树的直径就是所有节点 dnode的最大值减一。
算法流程为:我们定义一个递归函数 depth(node) 计算 dnode,函数返回该节点为根的子树的深度。先递归调用左儿子和右儿子求得它们为根的子树的深度 L 和 R ,则该节点为根的子树的深度即为
max(L,R)+1,该节点的 dnode值为 L+R+1,递归搜索每个节点并设一个全局变量 ans 记录 dnode的最大值,最后返回 ans-1 即为树的直径。
代码
class TreeNode(object): # Definition for a binary tree node.
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution(object):
def diameterOfBinaryTree(self, root):
"""
这种解法路径必须经过根节点,由题目可知路径可能穿过
也可能不穿过根节点,故此解法不符合题意
:type root: TreeNode
:rtype: int
"""
left = self.get_depth(root.left)
right = self.get_depth(root.right)
return left + right
def get_depth(self, root):
if not root:
return 0
left_depth = self.get_depth(root.left)
right_depth = self.get_depth(root.right)
return max(left_depth, right_depth) + 1
def diameterOfBinaryTree1(self, root):
self.ans = 1
def depth(node):
if not node:
return 0
L = depth(node.left)
R = depth(node.right)
self.ans = max(self.ans, L + R + 1)
return max(L, R) + 1
depth(root)
return self.ans - 1 # 一条路径的长度为该路径经过的节点数减一
if __name__ == "__main__":
slt = Solution()
root = TreeNode(1)
node2 = TreeNode(2)
node3 = TreeNode(3)
node4 = TreeNode(4)
node5 = TreeNode(5)
root.left = node2
root.right = node3
node2.left = node4
node2.right = node5
# diameter = slt.diameterOfBinaryTree(root)
diameter = slt.diameterOfBinaryTree1(root)
print("diameter:", diameter)