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

相关推荐
惜.己37 分钟前
数据结构与算法-数组异或操作
数据结构·算法
Dylan的码园39 分钟前
ArrayList与顺序表
java·数据结构·链表
2301_8079973840 分钟前
代码随想录-day55
数据结构·c++·算法
别动哪条鱼3 小时前
AAC ADTS 帧结构信息
网络·数据结构·ffmpeg·音视频·aac
Zsy_0510039 小时前
【数据结构】二叉树OJ
数据结构
程序员东岸10 小时前
《数据结构——排序(中)》选择与交换的艺术:从直接选择到堆排序的性能跃迁
数据结构·笔记·算法·leetcode·排序算法
程序员-King.11 小时前
day104—对向双指针—接雨水(LeetCode-42)
算法·贪心算法
牢七11 小时前
数据结构11111
数据结构
神仙别闹11 小时前
基于C++实现(控制台)应用递推法完成经典型算法的应用
开发语言·c++·算法