LC543 二叉树的直径¶
简单通过率 64.4%python3核心代码模式二叉树样例通过牛客 AC树深度优先搜索二叉树树形 DP
讲解章节:树的基础与遍历
一句话
每个节点算一次「左右两棵子树的高度之和」,取最大值。
解题思路¶
这题考什么¶
直径是任意两点间最长路径的边数。它和 LC124 的最大路径和同构: 任何一条路径都有唯一的最高点,以最高点为界拆成两条向下的链。 于是把「枚举路径」换成「枚举最高点」:
这里的「高度」按节点数算:空子树高度 0,叶子高度 1。 两个节点数之和为什么恰好就是边数?因为左边那条链有 h_left 个节点, 从 node 走到它的末端要跨 h_left 条边(node 到左孩子算第一条), 右边同理,合起来正是 h_left + h_right 条边。
高度本身满足 h(node) = max(h(左), h(右)) + 1,是一次后序遍历就能算完的量: 先把两个孩子结算好,再结算自己。这是树形动态规划(树形 DP)的最小样例, 树的直径的两种做法见 树的基础与遍历 的「树的直径」一节。
示例 1 的 [1,2,3,4,5]:
返回 3,对应路径 4 -> 2 -> 1 -> 3,与样例一致。
数据规模与复杂度¶
节点数在 [1, 10^4],节点值在 [-100, 100](值与答案无关,只有形状有关)。 每个节点被展开一次、结算一次,时间 O(n); 栈与高度表都是 O(n)(栈深不超过树高,链状树就是 n)。
坑在哪¶
- 必须迭代。n 到 1e4,最坏是一条链,递归深度 1e4, 远超 CPython 默认的 1000 层上限,递归版 RecursionError; 递归改迭代见 DFS 深度优先搜索 的 60.4 节。 这里用「进出两次」的后序遍历:第一次弹出只把自己和两个孩子重新压栈, 第二次弹出时孩子的高度都已经算好了。
- 答案按边数、高度按节点数,两个口径不能混。单节点树的直径是 0 而不是 1; 直接返回最大高度之类的写法会整体差一。
- 最长路径不一定经过根。示例里过根只是巧合,所以必须对每个节点都算一次 候选值;只在根上算一次会漏掉挂在深处的长路径。
- 高度表用节点的 id 当键,空孩子查不到时默认 0 —— 这正好就是 「空子树高度为 0」,不需要额外的判空分支。
- 答案初值取 0:题面保证至少一个节点,而单节点树没有任何边,直径就是 0, 不存在比它更小的合法答案。
参考实现¶
[:octicons-arrow-left-16: LC438](LC438.md) [LC560 :octicons-arrow-right-16:](LC560.md)