二叉树的深度和直径问题的具体思路(递归法)(附完整代码)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

想要求解一个二叉树的深度和直径,首先需要明确什么是二叉树的深度和直径。


一、二叉数的深度和直径是什么?

 二叉树的深度:从根节点到最远叶节点的最长路径上的节点数量。

 二叉树的直径:二叉树中任意两个节点之间的最长路径长度,这里的路径长度是指经过的边的数量。

如下是一个简单的二叉树:

      5
     / \
    3   8
   /   / \
  2   7   9
 /   /
1   6

根据上述概念我们可以很容易的找到:

该二叉树的深度为4(5-3-2-1或者5-8-7-6)
 
该二叉树的直径为6(1-2-3-5-8-7-6)

当二叉树的节点较少,结构比较简单的时候,我们可以一眼发现最长的那条路径,但如果希望通过代码来实现这个需求,我们应该怎么办呢?

现已知:我们的目的是找到最长的“路径”,那么最后我们一定要返回一个整数(用来表示这个树的深度/直径)。

因此我们可以定义一个函数用来计算深度/直径(传入树的节点参数,输出以该节点为根节点时的深度/直径)。

二、求二叉树的深度

定义一个函数 maxDepth,传入树的根节点,返回树的深度。
int maxDepth(TreeNode* root) {
    return maxp;
}

回看上图中的二叉树

      5
     / \
    3   8
   /   / \
  2   7   9
 /   /
1   6

当传入5这个节点(注意:传入的是节点root,而不是整数5)的时候,需要返回整数4(5-3-2-1或5-8-7-6)。

那么这个4是怎么得来的呢?

其实是当我们找5这个节点的深度时,相当于去找 “3这个节点” 和 “8这个节点” 的深度,因为当我们知道了这个两个节点为根节点时的深度,那么找到这两个里长度最长的那一条路径的长度再加上1,就是以5为根节点时的深度。

现在问题转化为了,如何找到 “3这个节点” 和 “8这个节点” 的树的深度,那么我们是不是依旧可以运用上述的方法,把问题转化为去找 “2这个节点” “7这个节点” “9这个节点”。

相信到这里,您已经发现问题的实质就是运用递归,逐级由上向下去找子树的深度,直到叶节点(最末端)。

定义递归函数length,传入节点,返回以传入节点为根节点时,树的深度。

定义maxp用来记录当前递归中哪条子树深度最大。
    int maxp=0;//最大节点数
    int length(TreeNode* root){
        if(root==nullptr){
            return 0;
        }
        int l=length(root->left);
        int r=length(root->right);
        maxp=max(l,r)+1;
        return maxp;
    }

完整代码如下

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
int maxp=0;//最大节点数
public:
    int maxDepth(TreeNode* root) {
        length(root);
        return maxp;
    }

    int length(TreeNode* root){
        if(root==nullptr){
            return 0;
        }
        int l=length(root->left);
        int r=length(root->right);
        maxp=max(l,r)+1;
        return maxp;
    }
};

采用深度优先搜索,时间复杂度为O(n)。


三、求二叉树的直径

定义一个函数diameterOfBinaryTree,传入节点,返回二叉树的直径。
int diameterOfBinaryTree(TreeNode* root) {
    return maxp-1;
}

相较于求解二叉树的深度,计算二叉树的直径需要同时计算根节点两侧的树的长度(或者计算节点数),因此在计算时,需要取左侧最长节点数+右侧最长节点数+1(这个根节点本身),才是最长路径的节点总数。

与深度计算同理,依旧采用递归的方法,在计算左侧(右侧)最长节点数时,用递归的方式,逐层算出,并记录最大值(因为在计算二叉树直径时,这条最长的路径未必会通过根节点,如下图:

	      5
	     / \
	    3   8
	   /  \   
	  2    7   
	 /      \
	1        6
   /          \
  9            10
	 (9-1-2-3-7-6-10)  共7个节点,长度为6
     (9-1-2-3-5-8)     共6个节点,长度为5

因此该直径并未经过根节点 5。

如下为具体的递归函数 :

int maxp=1;//最大节点数
int length(TreeNode* root){
        if(root==nullptr){
            return 0;
        }
        // 递归
        int l=length(root->left);//左子树(不算根节点)的节点数,不能设置为全局变量
        int r=length(root->right);//右子树
        maxp=max(maxp,l+r+1);//左+右+根
        return max(l,r)+1;
    }

完整代码:

 int maxp=1;//最大节点数
    int diameterOfBinaryTree(TreeNode* root) {
        length(root);
        return maxp-1;
    }
    int length(TreeNode* root){
        if(root==nullptr){
            return 0;
        }
        // 递归
        int l=length(root->left);//左子树(不算根节点)的节点数
        int r=length(root->right);//右子树
        maxp=max(maxp,l+r+1);//左+右+根
        return max(l,r)+1;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值