543. 二叉树的直径
一、算法逻辑(逐步通顺讲解每一步思路)
🎯 问题目标:
求二叉树中任意两个节点之间的最长路径(以边数计算)。
✅ 1️⃣ 初始化变量
-
ans
用于记录目前遍历过程中的最大直径(最长路径上的边数); -
与上一版本不同:本实现中,返回的深度以“边数”定义,而不是“节点数”;
-
即:空节点深度为 -1,叶子节点深度为 0。
-
✅ 2️⃣ 定义递归函数 depth(node)
目标:返回当前 node
为根节点的最大深度(边数表示)。
处理流程如下:
✅ 递归基:
-
如果
node
是None
,说明是空节点,返回 -1。
✅ 正常递归:
-
递归获取左右子树的深度,并在返回值上 +1,表示当前节点比子树多一层边:
✅ 直径更新:
-
每个节点可能作为一条最长路径的“中心节点”,该路径长度为
L + R
(左右边之和); -
用这个值更新最大值
ans
。
✅ 返回当前节点的最大深度(左右中更大的那一个):
✅ 3️⃣ 主调用逻辑
-
从根节点开始深度遍历;
-
递归完成后,
ans
中即保存了整棵树的最大直径(边数形式,无需再减 1); -
最终返回
ans
。
二、核心点总结
这段实现与传统写法不同之处在于:
✅ 把“深度”定义为边数而不是节点数,从而避免最后再手动减 1 的步骤,计算更直接。
-
使用
nonlocal ans
来更新封闭作用域内的变量; -
所有的直径判断都在递归过程中逐层进行更新;
-
核心仍是:后序遍历,自底向上构建子树信息并合并更新全局答案。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
ans = 0
def depth(node: Optional[TreeNode]) -> int:
if node is None:
return -1
L = depth(node.left)+1
R = depth(node.right)+1
nonlocal ans
ans = max(ans, L+R)
return max(L, R)
depth(root)
return ans
三、时间复杂度分析
-
每个节点只访问一次;
-
每次访问只做常数次操作;
时间复杂度:O(n),其中
n
为节点数。
四、空间复杂度分析
-
空间主要来自递归调用栈;
-
最坏情况为链状树 → O(n),最好情况为平衡树 → O(log n);
空间复杂度:O(h),其中
h
是树的高度。
✅ 总结一句话
本算法通过“将深度定义为边数”的方式,避免了最终再减 1 的步骤,依然使用后序递归 + 非局部变量更新最大直径的策略,在 O(n) 时间、O(h) 空间内求出二叉树的最大直径。该写法更贴近“边”的定义,简洁且逻辑紧凑。