12 . 二叉树的直径

题目介绍

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

二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root

两节点之间路径的 长度 由它们之间边数表示。

提示:

  • 树中节点数目在范围 [1, 104]
  • -100 <= Node.val <= 100
cpp 复制代码
class Solution {
public:
    int diameterOfBinaryTree(TreeNode* root) {
        
    }
};

全文3600字,阅读+思考 15min ( 递归第二阶段核心之作

原题链接 : 543. 二叉树的直径 - 力扣(LeetCode)


解析

1 . 本题需求很明确:给你一棵二叉树 (仍是给一个root代表整棵二叉树),要求求出这棵树的直径。

2 . 根据示例1和示例2的解释,直径就是某个根节点,其左边能延申最远的长度 + 右边能延申最远的长度

3 . 就这么一个参数且只能看到当前树的根节点和左右节点,必然是要用递归------才能代表它们也可以代表一棵树

递归------分步解析

为何取这个"标题"------其实是博主第一次的思路,接下来诸位听我娓娓道来

1 . 读完题包括示例,解析出:既然要算某棵树的左右边分别能延申的最大长度,我脑中灵光一闪------这就是求解"二叉树的深度"。

故先设计出了第一个函数,求解当前树的最大深度

求深度曾是我们的解析重点,到如今已经成为解题趁手的工具------09 二叉树的最大深度-CSDN博客

cpp 复制代码
class Solution {
public:
    int _depth(TreeNode* root)
    {
        if(root == nullptr) return 0;
        int leftd = _depth(root->left);
        int rightd = _depth(root->right);
        return leftd>rightd?leftd+1:rightd+1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        
    }
};

注:

a . 当前树的最大深度:如果左边深一点取leftd+1,反之取右边rightd+1
2 . 思路回归正轨:递归,下一句 :老两样------核心任务 递归出口

3 . 核心任务 :

在每个核心任务中,我是如此设计:既然要算出整棵树最大的直径,那就把每棵树的直径算出来,然后取最大。

而某棵树的直径 等于 以它为根(拐点)向左的深度 + 向右的深度,至于最大就要进行比较

4 . 于是我把核心任务一步一步完成,

a . 接下来是计算某棵树的直径

cpp 复制代码
class Solution {
public:
    // ...
    int _diameterOfBinaryTree(TreeNode* root) {
        if(root == nullptr) return 0;
        int maxleft = _depth(root->left); 
        int maxright = _depth(root->right);
        return maxleft+maxright;//计算当前树的直径 (左右子树的深度和)
    }
    int diameterOfBinaryTree(TreeNode* root) {
        
    }
};

注:

_diameterOfBinaryTree里,取名就看得出:

maxleft 拿到当前树的左树最大深度

maxright 拿到当前树的右树最大深度

以当前树root为拐点,那么这棵树的直径我就算出来了 :maxleft+maxright
b. 然后在上层(给出的接口)调用_diameterOfBinaryTree,算出所有树的直径后,取最大

cpp 复制代码
class Solution {
public:
    // ... 
    int diameterOfBinaryTree(TreeNode* root) {
        if(root == nullptr) return 0;
        int left = diameterOfBinaryTree(root->left);
        int right = diameterOfBinaryTree(root->right);
        int cur = _diameterOfBinaryTree(root);
        return max(max(left,right),cur);// 取出当前树最大的直径
    }
};

注:

1 . 相信你也看出来了,我在上层调用下层的_diameter算出了当前树的直径,但为了算出整棵树方便比较取最大,又得递归调用算出左树 右树

2 . 最后比较------ 当前树直径 左树直径 右树直径 取最大;向上返回,或许这个结果是 left 也许是 right 又或许是最终的结果

3 . 其实diameterOfBinaryTree的核心任务:取出当前树最大直径

4 . 递归出口 :判断root是否为空 ,深度_depth里 ,返回为0 无深度

_diameter里,返回为0,表示无直径

diameter里,返回0,表示无最大直径

完整代码:

cpp 复制代码
class Solution {
public:
    int _depth(TreeNode* root)
    {
        if(root == nullptr) return 0;
        int leftd = _depth(root->left);
        int rightd = _depth(root->right);
        return leftd>rightd?leftd+1:rightd+1;
    }
    int _diameterOfBinaryTree(TreeNode* root) {
        if(root == nullptr) return 0;
        int maxleft = _depth(root->left); 
        int maxright = _depth(root->right);
        return maxleft+maxright;//计算当前树的直径 (左右子树的深度)
    }
    int diameterOfBinaryTree(TreeNode* root) {
        if(root == nullptr) return 0;
        int left = diameterOfBinaryTree(root->left);
        int right = diameterOfBinaryTree(root->right);
        int cur = _diameterOfBinaryTree(root);
        return max(max(left,right),cur);// 计算当前树的最大直径
    }
};

时间线收束:

1 . 之所以这段思路 称为 :"递归------分步解析"------

2 . diameterOfBinaryTree的核心任务 :计算当前树的最大直径

_diameterOfBinaryTree的核心任务:计算当前树的直径(左右深度和)

_depth的核心任务 :计算当前树的深度

递归------双任务

优化写法,请重点掌握 :思想 + 代码

1 . "递归------分步解析"里,思路清晰、结果正确,虽然递归节点重复,但是它是对的嘛。"不管黑猫白猫,能捉老鼠的就是好猫"

2 . 但是,我们追求进步。且这个方法学会了很爽。
1 . "递归------分步解析"的递归------

核心任务 : 算出当前树的最大直径

递归出口 :root为空树,不存在最大直径

2 . 能否将 求解每棵树深度 和 计算每棵树的深度和结合一下?这是优化思路1

3 . 能否就递归整棵树一遍就能直接得到最大直径 ? 这是优化思路2

4 . 都能

5 . 引入一个输出型参数 ,用来记录当前获得的最大二叉树直径

cpp 复制代码
int _depth(TreeNode* root,int& maxdiameter)
    {
        if(root == nullptr) return 0;
        int leftd = _depth(root->left,maxdiameter);
        int rightd = _depth(root->right,maxdiameter);
        maxdiameter = max(leftd+rightd,maxdiameter);
        return leftd>rightd?leftd+1:rightd+1;
    }

注:

1 . maxdiameter :起点为 0 ;输出型参数:传入引用,它能一直实时更新和记录最大直径

2 . 当_depth获得了当前树的左边深度 和 右边深度,不妨给当前树一个机会:计算一下它的直径,是否能与maxdiameter媲美;若能,更新maxdiameter,若不能,也无妨

3 . 然后继续完成计算深度的任务

上层代码就如此调用:

cpp 复制代码
int diameterOfBinaryTree(TreeNode* root) {
        int maxdiameter = 0;
        _depth(root,maxdiameter);
        return maxdiameter;
    }

完整代码:

cpp 复制代码
class Solution {
public:
    int _depth(TreeNode* root,int& maxdiameter)
    {
        if(root == nullptr) return 0;
        int leftd = _depth(root->left,maxdiameter);
        int rightd = _depth(root->right,maxdiameter);
        maxdiameter = max(leftd+rightd,maxdiameter);
        return leftd>rightd?leftd+1:rightd+1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        int maxdiameter = 0;
        _depth(root,maxdiameter);
        return maxdiameter;
    }
};

注:

1 . 双任务执行 :计算当前树的深度 ,maxdiameter平等与每棵树的直径一决高下

2 . 输出型参数的妙用,切记切记

总结以及完整参考代码

cpp 复制代码
class Solution {
public:
    int _depth(TreeNode* root)
    {
        if(root == nullptr) return 0;
        int leftd = _depth(root->left);
        int rightd = _depth(root->right);
        return leftd>rightd?leftd+1:rightd+1;
    }
    int _diameterOfBinaryTree(TreeNode* root) {
        if(root == nullptr) return 0;
        int maxleft = _depth(root->left); 
        int maxright = _depth(root->right);
        return maxleft+maxright;//计算当前树的直径 (左右子树的深度)
    }
    int diameterOfBinaryTree(TreeNode* root) {
        if(root == nullptr) return 0;
        int left = diameterOfBinaryTree(root->left);
        int right = diameterOfBinaryTree(root->right);
        int cur = _diameterOfBinaryTree(root);
        return max(max(left,right),cur);// 计算当前树的最大直径
    }
};
cpp 复制代码
class Solution {
public:
    int _depth(TreeNode* root,int& maxdiameter)
    {
        if(root == nullptr) return 0;
        int leftd = _depth(root->left,maxdiameter);
        int rightd = _depth(root->right,maxdiameter);
        maxdiameter = max(leftd+rightd,maxdiameter);
        return leftd>rightd?leftd+1:rightd+1;
    }
    int diameterOfBinaryTree(TreeNode* root) {
        int maxdiameter = 0;
        _depth(root,maxdiameter);
        return maxdiameter;
    }
};

求深度:09 二叉树的最大深度-CSDN博客

如果不熟悉输出型参数,我们可以从这篇深度理解,这是二叉树阶段一核心之作:08 二叉树的中序遍历-CSDN博客

相关推荐
卷福同学4 小时前
QClaw内测体验,能用微信指挥AI干活了
人工智能·算法·ai编程
sali-tec4 小时前
C# 基于OpenCv的视觉工作流-章34-投影向量
图像处理·人工智能·opencv·算法·计算机视觉
xiaoye-duck4 小时前
《算法题讲解指南:递归,搜索与回溯算法--递归》--3.反转链表,4.两两交换链表中的节点,5.快速幂
数据结构·c++·算法·递归
Eward-an4 小时前
【算法竞赛/大厂面试】盛最多水容器的最大面积解析
python·算法·leetcode·面试·职场和发展
山栀shanzhi4 小时前
归并排序(Merge Sort)原理与实现
数据结构·c++·算法·排序算法
阿豪学编程4 小时前
LeetCode438: 字符串中所有字母异位词
算法·leetcode
Trouvaille ~4 小时前
【递归、搜索与回溯】专题(七):FloodFill 算法——勇往直前的洪水灌溉
c++·算法·leetcode·青少年编程·面试·蓝桥杯·递归搜索回溯
地平线开发者5 小时前
征程 6P codec decoder sample
算法·自动驾驶
地平线开发者5 小时前
征程 6X Camera 接入数据评估
算法·自动驾驶
Storynone5 小时前
【Day23】LeetCode:455. 分发饼干,376. 摆动序列,53. 最大子序和
python·算法·leetcode