(LeetCode) 543. Diameter of Binary Tree

本文探讨了如何求解二叉树的最大直径问题,即树中任意两点间路径的最大长度。通过递归算法,在计算树的深度同时记录左右子树最大深度之和,最终得出最长路径。

543. Diameter of Binary Tree

Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.

Example:
Given a binary tree

      1
     / \
    2   3
   / \     
  4   5    

Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].

思路

题干中所求的路径可以转化为求左右子树中最大的深度之和,所以在求树的深度的过程中保留最大的深度之和,即可求得结果。

代码

class Solution {
public:
    int diameterOfBinaryTree(TreeNode* root) {
        int result = 0;
        dps(root, result);
        return result;
    }


    int dps(TreeNode* root, int &result){
        if (root==NULL) return 0;
        int ld = dps(root->left, result) ;
        int rd = dps(root->right, result);
        result = max(ld + rd, result);
        return max(ld+1, rd+1);
    }
};
<think>题目:LeetCode 543. 二叉树的直径 给定一棵二叉树,计算它的直径。二叉树的直径是指树中任意两个节点之间最长路径的长度。这条路径可能穿过也可能不穿过根节点。 代码解释: 该代码使用深度优先搜索(DFS)后序遍历二叉树,在遍历过程中计算每个节点的左右子树的最大链长(即从该节点到叶子节点的最长路径上的边数),并更新全局最大直径(ans)。 具体步骤: 1. 定义内部函数dfs(node)用于计算以node为根节点的子树的最大链长(即从node到其叶子节点的最长路径的边数)。 2. 如果节点为空,返回-1(这样叶子节点的高度为0,因为叶子节点的左右子树返回-1,然后+1变成0)。 3. 递归计算左子树的最大链长,并加1(表示从当前节点到左子节点的边)。 4. 递归计算右子树的最大链长,并加1。 5. 在遍历每个节点时,计算以该节点为最高点的路径长度(即左链长+右链长),并更新全局最大值ans。 6. 返回当前节点的最大链长(即左右链长中的最大值),供其父节点使用。 注意:直径是路径上的边数,而不是节点数。在计算路径长度时,我们使用左右链长相加(即l_len + r_len),因为从当前节点的左子节点经过当前节点再到右子节点,路径长度为左链长+右链长(两条链)。 例如: 1 / \ 2 3 / \ 4 5 节点2的左链长为1(节点2->4),右链长为1(节点2->5),则以节点2为根的路径长度为2(1+1)。 节点1的左链长为2(节点1->2->4或1->2->5),右链长为1(节点1->3),则以节点1为根的路径长度为3(2+1),但实际最大直径是节点4到节点3(经过节点2和1)的路径,长度为3(边数)。 因此,最终答案为3。 代码中: - 对于叶子节点,dfs返回0(因为其左右子树返回-1,然后+1变成0,再取max(0,0)返回0)。 - 在递归过程中,每个节点都会更新一次ans,取当前ans和当前节点左右链长之和的最大值。 最后,调用dfs(root)后返回ans即可。 注意:nonlocal ans 用于在内部函数中修改外部函数的变量。</think>### 解答:LeetCode 543题 - 二叉树直径的解法 #### 代码功能 这段代码用于计算二叉树的**直径**(任意两节点间最长路径的长度)。它通过深度优先搜索(DFS)高效地计算了二叉树中所有可能路径的最大长度。 #### 核心算法解释 ```python class Solution: def diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int: ans = 0 # 存储最大直径结果 def dfs(node: Optional[TreeNode]) -> int: """深度优先搜索遍历二叉树 返回:以当前节点为起点的最长路径长度(边数) """ nonlocal ans # 引用外部作用域的ans变量 # 1. 递归终止条件:空节点 if node is None: return -1 # 空节点返回-1(使叶子节点高度为0) # 2. 递归计算左右子树高度 l_len = dfs(node.left) + 1 # 左子树高度+当前节点到左子节点的边 r_len = dfs(node.right) + 1 # 右子树高度+当前节点到右子节点的边 # 3. 更新全局最大直径 ans = max(ans, l_len + r_len) # 当前节点作为"拐点"的路径长度 # 4. 返回当前子树的最大高度 return max(l_len, r_len) # 当前节点作为路径端点的最长路径 dfs(root) # 从根节点开始遍历 return ans ``` #### 关键点解析 1. **返回值设计**: - 空节点返回 `-1` → 使叶子节点的高度计算为 `0`(符合高度定义) - 公式:`当前高度 = max(左高度, 右高度) + 1` - 例:叶子节点:`max(-1, -1) + 1 = 0` 2. **直径计算原理**: ```python ans = max(ans, l_len + r_len) ``` - 每个节点的直径 = 左子树高度 + 右子树高度 - 最大直径可能出现在任意子树中(不一定是经过根节点的路径) 3. **时间复杂度**: - O(N) - 每个节点只访问一次(N为节点数) - 空间复杂度:O(H) - 递归栈深度(H为树高度) #### 示例说明 考虑二叉树: ``` 1 / \ 2 3 / \ 4 5 ``` 计算过程: 1. 节点4/5:高度=0,直径=0 2. 节点2:左高=0+1=1,右高=0+1=1 → 直径=2 3. 节点3:高度=0,直径=0 4. 节点1:左高=1+1=2,右高=0+1=1 → 直径=3 5. 最终结果:max(0,0,2,0,3) = 3 #### 为什么这样设计? 1. **空节点返回-1**: - 保证叶子节点高度为0(直观合理) - 简化高度计算:`高度 = 子树高度 + 1` 2. **后序遍历(左右根)**: - 必须先在左右子树计算高度,才能计算当前节点的直径 3. **非局部变量ans**: - 在DFS过程中持续更新全局最大值 - 避免额外数据结构存储中间结果 > **关键结论**:该解法通过DFS后序遍历,在O(N)时间内高效计算了二叉树的最大直径,是解决此类问题的标准解法。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值