Leetcode daily 20/03/10 二叉树的直径
二叉树的直径
-题目-
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。
-示例-
给定二叉树
1
/ \
2 3
/ \
4 5
返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
注意:两结点之间的路径长度是以它们之间边的数目表示。
-方法1-
对于一棵子树\(t_i\),其直径di
为任意两个节点路径长度最大值,也就是:(左子树 \(t_{left}\) 到某叶节点的距离最大值 + 1) + (右子树 \(t_{right}\) 到某叶节点的距离最大值 + 1)。如果左子树或右子树为空,则此子树\(t_i\)的直径di
为:(非空子树 \(t_{notNone}\) 到某叶节点的距离最大值 + 1)。若左右子树皆空,则该子树\(t_i\)的直径di
为0。
整棵树的直径就是每棵子树的直径的最大值max(\(d_i\))。
算法:
- 设置全局变量
rst
。 - 遍历树:
- 对每一棵子树求直径
di
。 - 取
di
和rst
较大值为rst
。
- 对每一棵子树求直径
- 最后得到的
rst
为整棵树的直径。
-ac代码-
class Solution:
def __init__(self):
self.rst = 0
def maxD(self, root):
maxLD = self.maxD(root.left) + 1 if root.left else 0
maxRD = self.maxD(root.right) + 1 if root.right else 0
di = maxLD + maxRD
self.rst = max(self.rst, di)
return max(maxLD, maxRD)
def diameterOfBinaryTree(self, root: TreeNode) -> int:
if not root:
return 0
self.maxD(root)
return self.rst
-复杂度-
- \(T(n) = O(n)\) (遍历每个节点求直径\(d_i\))
- \(S(n) = O(depth)\) (递归需要栈,栈长度为树深度)
-方法2-
子树\(t_i\)的直径di
也可以是:左子树深度depthL
+ 右子树深度depthR
。若子树为空,则深度为0,否则为(左子树深度depthL
和右子树深度depthR
较大值) + 1。
算法:
- 设置全局变量
rst
。 - 遍历树:
- 对每一棵子树求直径
di
。 - 取
di
和rst
较大值为rst
。
- 对每一棵子树求直径
- 最后得到的
rst
为整棵树的直径。
-ac代码-
class Solution:
def __init__(self):
self.rst = 0
def depth(self, root):
if not root:
return 0
depthL = self.depth(root.left)
depthR = self.depth(root.right)
di = depthL + depthR
self.rst = max(self.rst, di)
return max(depthL, depthR) + 1
def diameterOfBinaryTree(self, root: TreeNode) -> int:
if not root:
return 0
self.depth(root)
return self.rst
-复杂度-
- \(T(n) = O(n)\) (遍历每个节点求直径\(d_i\))
- \(S(n) = O(depth)\) (递归需要栈,栈长度为树深度)
-笔记-
- 题目-笔记:题目求的是两个节点之间路径(边数)最大值,可能不包含根节点。
- 算法-笔记:
if root.right is None:
return self.maxD(root.left) + 1
elif root.left is None:
return self.maxD(root.right) + 1
elif root.left is None and root.right is None:
return 0
以上代码第三个if
不会被执行。
- 算法-笔记:空节点可能需要额外操作。