力扣最热一百题——二叉树的直径

目录

[题目链接:543. 二叉树的直径 - 力扣(LeetCode)](#题目链接:543. 二叉树的直径 - 力扣(LeetCode))

题目描述

示例

提示:

解法一:深度优先搜索

实现思路:

关键点:

Java写法:

运行时间

C++写法:

运行时间

总结


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

注:下述题目描述和示例均来自力扣

题目描述

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

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

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

示例

示例 1:

复制代码
输入:root = [1,2,3,4,5]
输出:3
解释:3 ,取路径 [4,2,1,3] 或 [5,2,1,3] 的长度。

示例 2:

复制代码
输入:root = [1,2]
输出:1

提示:

  • 树中节点数目在范围 [1, ]
  • -100 <= Node.val <= 100

解法一:深度优先搜索

直径是二叉树中任意两节点间最长路径的长度。思路是通过深度优先遍历来逐个节点进行递归计算,最终找出最长路径。

实现思路:

  1. 全局变量res的作用

    • 该变量用于动态保存当前发现的最长路径。初始值设为0,但在进入根节点时被初始化为1,因为树至少包含根节点。
  2. diameterOfBinaryTree方法

    • 入口方法,接收二叉树的根节点作为输入。
    • 首先检查根节点是否为空,若为空,则二叉树的直径为0
    • 调用辅助方法depthFirst,以深度优先的方式遍历整棵树。
    • 最终返回res - 1,这是因为路径的长度是节点数减1。
  3. 深度优先遍历 depthFirst

    • 每个节点通过递归方式遍历其左子树和右子树,分别获取左子树和右子树的深度。
    • 更新全局变量res,这个过程通过比较当前节点左子树和右子树的深度和当前保存的res,取最大的那个值。res的更新逻辑是左子树深度 + 右子树深度 + 1(代表当前节点)。
    • 返回当前节点的深度,即左子树和右子树深度的最大值加1,作为给上层节点使用的深度值。

关键点:

  • 深度优先搜索 (DFS):通过递归的方式遍历每一个节点。
  • 动态维护最长路径 :每次计算出左右子树的深度时,更新全局变量res,并确保保存的是最长路径。
  • 最终结果调整 :二叉树的直径是节点数减去1(路径的长度是节点数减1),因此最后返回res - 1

Java写法:

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    // 定义一个全局变量用于动态保存res
    int res = 0;
    public int diameterOfBinaryTree(TreeNode root) {
        if(root != null){
            res = 1;
        }else{
            return 0;
        }
        // 深度优先遍历
        depthFirst(root);
        // 由于我们最终得到是节点的个数
        // 而题目要的是路径的长度,那么只需要-1即可
        return res - 1;

    }
    /**
        深度优先遍历
     */
    public int depthFirst(TreeNode node){
        // 非空判断
        if(node == null){
            return 0;
        }
        // 遍历左子树
        int leftDepth = depthFirst(node.left);
        // 遍历右子树
        int rightDepth = depthFirst(node.right);
        // 动态维护res,由于我们要找的是最长两个节点的长度
        // 那么res的值=左子树的深度+右子树的深度+node节点(也就是1)
        res = Math.max(res, leftDepth + rightDepth + 1);
        // 返回当前树的深度给上一节点
        return Math.max(leftDepth,rightDepth) + 1;
    }
}
运行时间

C++写法:

cpp 复制代码
/**
 * 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 {
public:
    // 定义一个全局变量用于动态保存res
    int res = 0;
    int diameterOfBinaryTree(TreeNode* root) {
        if(root == NULL){
            return 0;
        }else{
            res = 1;
        }
        // 深度优先遍历
        depthFirst(root);
        // 由于我们最终得到是节点的个数
        // 而题目要的是路径的长度,那么只需要-1即可
        return res - 1;
    }
    /**
        深度优先遍历
     */
    int depthFirst(TreeNode* node){
        // 非空判断,结束条件
        if(node == NULL){
            return 0;
        }
         // 遍历左子树
        int leftDepth = depthFirst(node->left);
         // 遍历右子树
        int rightDepth = depthFirst(node->right);
        // 动态维护res,由于我们要找的是最长两个节点的长度
        // 那么res的值=左子树的深度+右子树的深度+node节点(也就是1)
        res = max(res, leftDepth + rightDepth + 1);
         // 返回当前树的深度给上一节点
        return max(leftDepth,rightDepth) + 1;
    }
};
运行时间

总结

其实就是深度优先搜索的一个扩展现实,多维护了一个res结果,在每次的深度优先搜索的过程中动态的维护一个res,来坚持判断当前两个最远的节点的值,这里最远的节点的值,肯定是存在于两个叶子结点之间的(其实我也在思考这句话对不对,我目前分析来说是对的,没有找到反例,不知道各位同学、大佬能不能发现这句话的问题,欢迎指正),这就是这道题目的关键点所在。

相关推荐
劲夫学编程42 分钟前
leetcode:杨辉三角
算法·leetcode·职场和发展
毕竟秋山澪44 分钟前
孤岛的总面积(Dfs C#
算法·深度优先
阿伟*rui2 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
浮生如梦_3 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
XiaoLeisj4 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck4 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei4 小时前
java的类加载机制的学习
java·学习
励志成为嵌入式工程师5 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法