LeetCode - 543. 二叉树的直径
目录
题目
思路解析
读者可能出现的错误写法
正确写法
题目
543. 二叉树的直径 - 力扣(LeetCode)
思路解析
这个算法的思路是通过深度优先搜索(DFS)来计算二叉树的直径:
定义直径:二叉树的直径是指树中任意两个节点之间的最长路径长度。这个路径可能会穿过根节点,也可能不穿过。
关键洞察:对于树中的任意一个节点,经过该节点的最长路径长度等于其左子树的最大深度加上右子树的最大深度。
递归计算:
- 对每个节点,计算其左右子树的最大深度
- 用左右子树深度之和更新全局最大直径
- 返回当前节点为根的子树的最大深度(即左右子树深度的较大值加1)
结果:遍历完整棵树后,全局变量 result 中存储的就是树的直径
读者可能出现的错误写法
class Solution {
public:int diameterOfBinaryTree(TreeNode* root) {int result = 0;dfs(root,result);return result;}int dfs(TreeNode* root,int result){if(!root){return 0;}int left = dfs(root->left,result);int right = dfs(root->right,result);result = max(left,right);return max(left,right) + 1;}
};
参数传递问题:result 参数没有使用引用传递,而是值传递。这意味着在 dfs 函数中对 result 的修改不会影响到调用者中的 result 变量。
- 修正:将参数改为引用类型 int& result
直径计算错误:直径计算应该是左子树深度加右子树深度,而不是取它们的最大值。
- 修正:result = max(result, left + right);
为啥这个深度要相加? 它算深度不就是算高度吗?
二叉树的直径是指树中任意两个节点之间的最长路径长度。这个路径不一定要经过根节点,但一定会经过某个节点,该节点成为这条路径的"最低公共祖先"。
对于任意一个节点,以它为"最低公共祖先"的最长路径长度是什么?是它左子树的最大深度加上右子树的最大深度。
举例说明:
- 假设有一个节点N
- 它的左子树最大深度是L(即从N到左子树最远叶子节点的边数)
- 它的右子树最大深度是R(即从N到右子树最远叶子节点的边数)
- 那么经过节点N的最长路径长度就是L+R
这是因为:
- 最长路径必定从左子树的某个叶子节点,经过节点N,再到右子树的某个叶子节点
- 为了使路径最长,我们选择左右子树中最深的叶子节点
- 因此路径长度 = 左子树最大深度 + 右子树最大深度
在递归过程中:
- 函数返回的是节点的高度(从该节点到最远叶子节点的边数)
- 而更新直径时,我们考虑的是经过该节点的最长路径(左子树高度+右子树高度)
正确写法
class Solution {
public:int diameterOfBinaryTree(TreeNode* root) {int result = 0;dfs(root,result);return result;}int dfs(TreeNode* root,int result){if(!root){return 0;}int left = dfs(root->left,result);int right = dfs(root->right,result);result = max(result,left+right);return max(left,right) + 1;}
};