图解题库 / 二叉树 · 树形DP

543. 二叉树的直径

简单 含交互动画

学完这道你应该能: 说清它为什么用「树形DP」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

求任意两节点路径长度(边数)的最大值。这条路不一定经过根。

= 1 →(2,3), 2 →(4,5)
输出 = 3 (路径 4→2→1→3)

思路解析

复用最大深度的递归:算每个节点深度的时候,顺便算一下“穿过它的最长路径”,就是左子树深度 + 右子树深度。我们一边后序遍历算深度,一边用一个全局变量记下这个和的最大值,最后就是直径。

叶子 · 深度 1:叶子节点 4、5、3 的深度都是 1。穿过叶子的路径长度 = 0+0 = 0。

节点 2 · 左深+右深 = 2:节点 2 的左子树深度(4)是 1,右子树深度(5)是 1。穿过 2 的最长路径 = 1+1 = 2,也就是 4→2→5。更新直径 = 2。同时 depth(2) = 1 + max(1,1) = 2。

根 1 · 左深+右深 = 3:根节点 1 的左子树深度(2)是 2,右子树深度(3)是 1。穿过根的最长路径 = 2+1 = 3,也就是 4→2→1→3。更新直径 = 3,这就是答案。

这是一类树形题的通用套路:递归返回一个“能拼给父节点”的量(比如深度),同时用全局变量记录一个“在当前节点结算”的答案(比如穿过它的路径)。像最大路径和(124)、最长同值路径都是这个套路。

参考代码(Python)

Python
1self.diameter = 0
2def depth(node):
3    if not node: return 0
4    L = depth(node.left)
5    R = depth(node.right)
6    self.diameter = max(self.diameter, L + R)  # 穿过它的路
7    return 1 + max(L, R)                       # 返回深度
8depth(root); return self.diameter

复杂度分析

  • 时间复杂度:O(n) —— 一次后序遍历
  • 空间复杂度:O(h) —— 递归栈

套路模板

记住这个骨架:全局变量在当前节点“结算横跨路径”,返回值给父节点“向上延伸”。分清这两者,这类题就不容易出错。

Python
1self.ans = 初值
2def dfs(node):
3    if not node: return 0
4    L, R = dfs(node.left), dfs(node.right)
5    self.ans = max(self.ans, 用 L,R 在此结算)   # 经过当前点的答案
6    return 能向上拼接的量(L, R, node)            # 给父亲用

易错点

  • 返回 L+R 给父亲 → ✅ 返回 1+max(L,R)(给父亲的是深度(只能选一条边往上),不是横跨路径)
  • 直径按节点数算 → ✅ 直径是边数 = L+R(深度按节点、直径按边,差一要分清)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →236. 最近公共祖先 ← 返回题库