首页 > 试题广场 >

二叉树的直径

[编程题]二叉树的直径
  • 热度指数:2764 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一颗二叉树,求二叉树的直径。
1.该题的直径定义为:树上任意两个节点路径长度的最大值
2.该题路径长度定义为:不需要从根节点开始,也不需要在叶子节点结束,也不需要必须从父节点到子节点,一个节点到底另外一个节点走的边的数目
3.这个路径可能穿过根节点,也可能不穿过
4.树为空时,返回 0
如,输入{1,2,3,#,#,4,5},二叉树如下:

那么:
4到5的路径为4=>3=>5,路径长度为2
从4到2的路径为4=>3=>1=>2,路径长度为3

如,输入{1,2,3,#,#,4,5,9,#,#,6,#,7,#,8},二叉树如下:
那么路径长度最长为:7=>9=>4=>3=>5=>6=>8,长度为6

数据范围:节点数量满足
示例1

输入

{1,2,3,#,#,4,5}

输出

3
示例2

输入

{1,2,3,#,#,4,5,9,#,#,6,#,7,#,8}

输出

6
示例3

输入

{1,2,3}

输出

2

说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
树型DP套路。对于以某个节点为根节点的子树,有如下两种情况:
                                  
  1. 当前节点不参与路径,此时左右子树中最大路径较大的那个就是当前节点不参与路径时的最长路径。如上图红色节点(根节点)的子树中,最长路径就是两个黄色节点经过蓝色节点的路径,并未经过红色节点自身。
  2. 当前节点参与路径,此时最大的路径应该是:左树高+右树高+1(1为当前节点)。如上图中蓝色节点的子树中,最长路径就是两个黄色节点经过自己的那条路径。
这时候对于某个节点而言,只要向左右孩子节点收集信息,就能够计算它的最大路径,需要的信息有:(1) 左子树高度;(2) 右子树高度;(3) 左右孩子的最长路径。根据信息(3)我们可以求得当前节点不参与路径时的最长路径;根据信息(1)和(2)我们可以求得当前节点参与路径时的最长路径。而为了在根节点汇总整棵树的信息,每个节点需要把当前收集到的信息做一个汇总,方便自己的父节点使用:
  1. 计算以当前节点为根节点的子树高度:height=max(left_height, right_height)+1
  2. 以当前节点为根节点的子树所包含的最大路径长度:max(左子树最大路径, 右子树最大路径, 左树高+右树高+1)
但是本题的路径长度并不是节点个数,而是边的条数,因此最终的结果需要-1,且保证不为负数
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */
class Info {
    public int maxDistance;
    public int height;
    public Info(int maxDistance, int height) {
        this.maxDistance = maxDistance;
        this.height = height;
    }
}


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return int整型
     */
    public int diameterOfBinaryTree (TreeNode root) {
        // write code here
        return Math.max(process(root).maxDistance - 1, 0);
    }
    
    private Info process(TreeNode node) {
        if(node == null){
            return new Info(0, 0);
        }
        // 向左右子树收集信息
        Info leftInfo = process(node.left);
        Info rightInfo = process(node.right);
        int path1 = leftInfo.height + rightInfo.height + 1;     // 头结点参与的距离
        int path2 = Math.max(leftInfo.maxDistance, rightInfo.maxDistance);     // 头结点不参与的距离
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;
        return new Info(Math.max(path1, path2), height);
    }
}

发表于 2021-11-21 09:50:46 回复(0)
int res=0;
    public int diameterOfBinaryTree (TreeNode root) {
        dfs(root);
        return res;
    }
    public int dfs(TreeNode root){
        if(root==null) return 0;
        int left=dfs(root.left);
        int right=dfs(root.right);
        res=Math.max(res,left+right);
        return Math.max(left,right)+1;
    }

发表于 2021-11-26 19:06:28 回复(0)
int max = 0;
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return int整型
     */
    public int diameterOfBinaryTree (TreeNode root) {
        if(root == null) return 0;
        max = Math.max(max, maxC(root.left) + maxC(root.right));
        diameterOfBinaryTree(root.left);
        diameterOfBinaryTree(root.right);
        return max;
    }
    /**
     * 某个节点的最大层数
     */
    private int maxC(TreeNode root) {
        if(root == null) return 0;
        return Math.max(maxC(root.left), maxC(root.right)) + 1;
    }

发表于 2023-06-06 08:50:43 回复(0)
import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return int整型
     */
     int max=0;
    public int diameterOfBinaryTree (TreeNode root) {
        // write code here
        getDepth(root);
        return max;
    }
    public int getDepth(TreeNode root){
        if(root==null){
            return 0;
        }
        int left=getDepth(root.left);
        int right=getDepth(root.right);
        max=Math.max((left+right),max);
        return Math.max(left,right)+1;
    }
}

发表于 2023-05-19 10:59:55 回复(0)
class Solution:
    def diameterOfBinaryTree(self , root: TreeNode) -> int:
        # write code here 
        def height(root):
            # 返回该节点的深度
            if not root:
                return 0 
            return max(1 + height(root.left), 1 + height(root.right))
        l = []
        def dfs(root):
            # 遍历二叉树,将每个节点的直径放入列表
            if not root:
                return 
            # 直径 = 左子树深度 + 右子树深度
            diameter = height(root.left) + height(root.right)
            l.append(diameter)
            dfs(root.left)
            dfs(root.right)
        
        dfs(root)
        return max(l) if len(l) > 0 else 0

发表于 2023-04-27 12:09:11 回复(0)
package main
// import "fmt"
import . "nc_tools"
/*
 * type TreeNode struct {
 *   Val int
 *   Left *TreeNode
 *   Right *TreeNode
 * }
 */

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param root TreeNode类 
 * @return int整型
*/
func diameterOfBinaryTree( root *TreeNode ) int {
    if root==nil{
        return 0
    }
    return max(cal(root.Left)+cal(root.Right),max(cal(root.Left),cal(root.Right)))
}

func cal(root *TreeNode)int{
    if root==nil{
        return 0
    }
    cnt:=1
    cnt+=max(cal(root.Left),cal(root.Right))
    return cnt
}

func max(a,b int)int{
    if a>b{
        return a
    }
    return b
}

发表于 2023-01-31 22:12:52 回复(0)
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param root TreeNode类 
 * @return int整型
 */
 //以 root 为头结点的树,最大直径就是左右两个子树的高度相加 
 int dfs(struct TreeNode* root){
    if(NULL==root)
       return 0;
    else{
        return (dfs(root->left)>dfs(root->right)?dfs(root->left):dfs(root->right))+1;
    }
 }
int diameterOfBinaryTree(struct TreeNode* root ) {
    // write code here
    if(root==NULL)
      return NULL;
    return dfs(root->left)+dfs(root->right);
}

发表于 2023-01-10 23:01:19 回复(0)
mlgb的下次别给的case和数据范围不一致好不好 说好的100个点给了1000个点。100个点就不一定树形dp了好吧,随便一个floyd都可以干了。
发表于 2022-08-21 18:52:14 回复(0)
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return int整型
     */
    int diameterOfBinaryTree(TreeNode* root) {
        // write code here
        if(root == NULL)    return 0;
        return max(max(diameterOfBinaryTree(root->left),diameterOfBinaryTree(root->right)),lengthOfBinaryTree(root->left) + lengthOfBinaryTree(root->right));
    }
    int lengthOfBinaryTree(TreeNode* root){
        if(root == NULL)    return 0;
        return 1 + max(lengthOfBinaryTree(root->left),lengthOfBinaryTree(root->right));
    }
};

发表于 2022-07-30 14:36:20 回复(0)
# -*- coding: utf-8 -*-

import sys

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class BT(object):
    def __init__(self):
        self.root = None

    def levelOrderToBT(self, nums):
        n = len(nums)

        if n > 0:
            self.root = TreeNode(nums[0])
            queue, idx = [self.root], 1
            while queue and idx < n:
                curNode = queue.pop(0)
                curNode.left = TreeNode(nums[idx]) \
                    if nums[idx] != None else None
                if curNode.left:
                    queue.append(curNode.left)
                curNode.right = TreeNode(nums[idx + 1]) \
                    if idx + 1 < n and nums[idx + 1] != None else None
                if curNode.right:
                    queue.append(curNode.right)
                idx += 2

        return self.root

    @staticmethod
    def levelOrder(root):
        if not root:
            return []

        queue, res = [root], []
        while queue:
            node = queue.pop(0)
            if node:
                res.append(node.val)
                queue.append(node.left)
                queue.append(node.right)
            else:
                res.append(None)
        while res and res[-1] == None:
            res.pop()

        return res


#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param root TreeNode类
# @return int整型
#
class Solution:
    """
    题目:
        NC195 二叉树的直径
        https://www.nowcoder.com/practice/15f977cedc5a4ffa8f03a3433d18650d?tpId=117&&tqId=39370&rp=1&ru=/ta/job-code-high&qru=/ta/job-code-high/question-ranking
    参考:
        大神:君无颜
    算法:
        关键点:以当前节点为头结点的树,直径就是左右两个子树的高度相加,故最大直径属于在如下三种情况之一:
            1. 最大直径包含root:以 root 为头结点的树,最大直径就是左右两个子树的高度相加
            2. 最大直径出现在root的左子树:左子树的直径是以 root->left 为头结点的树,最大直径同理
            3. 最大直径出现在root的右子树:右子树的直径是以 root->right 为头结点的树,最大直径同理
        最后,取三者最大值即可。
    复杂度:
        时间复杂度:O(N),N为二叉树的节点数
        空间复杂度:O(H),H为二叉树的高度
    """

    def diameterOfBinaryTree(self, root):
        # write code here
        def getHeight(root):
            if not root:  # 空子树的高度为0
                return 0
            lHeight, rHeight = getHeight(root.left), getHeight(root.right)
            self.res = max(self.res, lHeight + rHeight)
            return lHeight + 1 if lHeight > rHeight else rHeight + 1

        self.res = 0
        sys.setrecursionlimit(1500)
        getHeight(root)
        return self.res


if __name__ == '__main__':
    s = Solution()

    # nums = [1, 2, 3, None, None, 4, 5]

    # nums = [1, 2, 3, None, None, 4, 5, 9, None, None, 6, None, 7, None, 8]

    # nums = [1, 2, 3]

    nums = []

    bt = BT()
    bt1 = bt.levelOrderToBT(nums)
    # print BT.levelOrder(bt1)

    res = s.diameterOfBinaryTree(bt1)
    print res

发表于 2022-07-07 08:35:36 回复(0)
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return int整型
     */

    int diameterOfBinaryTree(TreeNode* root) {
        // write code here
        if(!root) return 0;
        int Lmax = 0;
        search(root, Lmax);
        return Lmax;
    }
    
    int search(TreeNode* node, int & Lmax)
    {
        if(!node) return 0;
        int left = search(node->left, Lmax);
        int right = search(node->right, Lmax);
        Lmax = Lmax < left + right ? left + right : Lmax;
        return max(left, right) + 1;
    }
};


发表于 2022-05-02 16:52:07 回复(0)
//后序遍历

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @return int整型
     */
    int res = 0;
    int diameterOfBinaryTree(TreeNode* root) {
        // write code here
        dfs(root);
        return res;
    }
    int dfs(TreeNode* root){
        if(!root) return 0;
        int l = dfs(root->left) ;
        int r = dfs(root->right) ;
        res = max(res,l + r);
        return max(l,r) + 1;
    }
};

发表于 2022-03-01 21:42:29 回复(0)
class Solution {
public:
    int res1 = 0;
    int diameterOfBinaryTree(TreeNode* root) {
        // write code here
        diameter(root);
        return res1;
    }
    int diameter(TreeNode* root) {
        if(root == nullptr) return 0;
        int left= diameter(root->left);
        int right= diameter(root->right);
        res1 = (left+right)>res1?(left+right):res1;
        return  left>right?left+1:right+1;
    }
};

C++ ?:条件运算符(三目运算符)



发表于 2022-02-22 10:40:00 回复(0)
class Solution:
    def diameterOfBinaryTree(self , root: TreeNode) -> int:
        # 递归+计算树的最大深度
        self.best=0
        def depth(root):
            if not root:
                return 0
            left=depth(root.left)
            right=depth(root.right)
            self.best=max(self.best,left+right)
            return max(left,right)+1
        
        de=depth(root)
        
        return self.best
    
 

发表于 2022-01-12 07:16:12 回复(0)