三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

力扣刷题#31-0543-二叉树的直径

力扣刷题#31-0543-二叉树的直径

力扣刷题#31-0543-二叉树的直径

题目

给你一棵二叉树的根节点,返回该树的直径。

二叉树的直径是指树中任意两个节点之间最长路径的长度。这条路径可能经过也可能不经过根节点。路径长度由它们之间边数表示。

输入: root = [1,2,3,4,5]1/ \2   3/ \4   5
输出: 3
解释: 最长路径是 4→2→1→3 或 5→2→1→3,长度 3(3 条边)

我的思路之旅

第一反应:左子树深度 + 右子树深度?

看到"最长路径",我第一反应是:左子树跑一遍 DFS 求深度,右子树也跑一遍,相加就是直径。

这个想法对"经过根节点"的路径成立,但题目明确说"可能不经过根节点"——直径可能完全藏在某一侧子树里:

        1/ \2    3/ \4   5/ \6   7直径 = 6→4→2→5 这条(藏在左子树内部)
如果只算根的左+右:深度(左子树2)=3,深度(右子树3)=1 → 3+1=4
但真实直径在左子树内部是 6→4→2→5 = 3 条边... 

只算根节点会漏掉藏在子树内部的更长路径。


关键洞察:每个节点都可能是"拐点"

任意一条直径路径,一定有一个最高点(路径的转折点)。所以正确答案是:

对每个节点 node:穿过它的最长路径 = node左子树深度 + node右子树深度用这个值更新全局最大值 ansDFS 返回 node 的深度(较深那侧 + 1),供父节点使用

一次 DFS 干两件事:返回深度给父节点 + 顺手用局部路径长度更新全局最大值。

生活化类比

测量整座山脉的最长山路。不能只看主峰——要从每个山头都出发算一遍"从它这个山脊往左右延伸最长能多远",取所有山头里最大的那个。


我的 AC 代码

class Solution {
public:int ans = 0;int dfs(TreeNode* root) {if (root == nullptr) return 0;int left = dfs(root->left);int right = dfs(root->right);ans = max(left + right, ans);return max(left, right) + 1;}int diameterOfBinaryTree(TreeNode* root) {dfs(root);return ans;}
};

代码逐段解析

第 3 行:全局变量

int ans = 0;

成员变量,跨越所有递归调用共享。记录"穿过每个节点的最长路径"的最大值。

第 5-6 行:递归出口

if (root == nullptr) return 0;

空节点深度为 0。

第 7-8 行:左右深度

int left = dfs(root->left);
int right = dfs(root->right);

递归拿到左右子树的深度。先信任子树能算出来——这就是递归思维。

第 9 行:更新全局答案

ans = max(left + right, ans);

穿过当前节点的路径 = 左深度 + 右深度。不断和全局最大值比,取更大者。

第 11 行:返回深度

return max(left, right) + 1;

本子树的深度 = 较深那侧 + 1(自己这一层),供父节点继续用。

第 15-17 行:入口

int diameterOfBinaryTree(TreeNode* root) {dfs(root);return ans;
}

调用一次 DFS,期间 ans 被所有节点更新过,最后直接返回。


为什么这个解法能覆盖"不经过根"的情况?

因为 ans = max(left + right, ans)每一个节点都会执行一次。

        1/ \2    3/ \4   5dfs(4): left=0, right=0 → ans=max(0,0)=0 → return 1
dfs(5): left=0, right=0 → ans=max(0,0)=0 → return 1
dfs(2): left=1, right=1 → ans=max(2,0)=2 → return 2   ← 2 就是路径 4→2→5 的长度
dfs(3): left=0, right=0 → ans=max(0,2)=2 → return 1
dfs(1): left=2, right=1 → ans=max(3,2)=3 → return 3   ← 1 这里更新为 3最终 ans = 3 ✓

无论直径的拐点在哪一层,那个节点的 left+right 都会更新 ans


复杂度分析

维度 说明
时间复杂度 O(n) 每个节点访问一次
空间复杂度 O(h) 递归栈深度 = 树高

关键点总结

关键点 说明
核心套路 DFS + 全局变量:一次遍历干两件事
返回什么 子树的深度(max(左,右)+1)
更新什么 穿过当前节点的路径长(left+right)
为什么对 每个节点都当"拐点"更新一次,覆盖不经过根的路径
我的弯路 只算根的左+右 → 漏掉子树内部更长的路径

本文档由 AI 辅助生成,作者提供问题,思路和代码,AI仅负责文本修饰,综合获得以上内容。

← 返回列表