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博客

相关推荐
机器学习之心5 分钟前
基于PSO-GA混合算法的施工进度计划多目标优化,以最小化总成本并实现资源均衡,满足工期约束和资源限制,MATLAB代码
算法·matlab·多目标优化·pso-ga混合算法
bbq粉刷匠8 分钟前
Java--二叉树概念及其基础应用
java·数据结构·算法
CodeByV9 分钟前
【算法题】前缀和
算法
高洁0117 分钟前
知识图谱构建
人工智能·深度学习·算法·机器学习·知识图谱
郝亚军17 分钟前
顺序栈C语言版本
c语言·开发语言·算法
Cowboy hat21 分钟前
数据结构基础(二):线性数据结构
数据结构
AndrewHZ24 分钟前
【图像处理基石】什么是神经渲染?
图像处理·人工智能·神经网络·算法·cnn·计算机图形学·神经渲染
2401_8414956427 分钟前
【LeetCode刷题】爬楼梯
数据结构·python·算法·leetcode·动态规划·滑动窗口·斐波那契数列
byzh_rc30 分钟前
[模式识别-从入门到入土] 组合分类器
人工智能·算法·机器学习·支持向量机·概率论
风筝在晴天搁浅40 分钟前
hot100 142.环形链表Ⅱ
数据结构·链表