【经典算法】LeetCode104二叉树的最大深度(Java/C/Python3实现含注释说明,Easy)

news2024/12/23 7:31:37

目录

  • 题目描述
  • 思路及实现
    • 方式一:递归
      • 思路
      • 代码实现
        • Java版本
        • C语言版本
        • Python3版本
        • Go语言版本
      • 复杂度分析
    • 方式二:广度优先搜索(BFS)
      • 思路
      • 代码实现
        • Java版本
        • C语言版本
        • Python3版本
      • 复杂度分析
  • 总结
  • 相似题目

  • 标签(题目类型):树、深度优先搜索(DFS)、广度优先搜索(BFS)、递归、迭代

题目描述

给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

示例 1:

在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:3
示例 2:

输入:root = [1,null,2]
输出:2
提示:

树中节点的数量在 [0, 104] 区间内。
-100 <= Node.val <= 100

原题:LeetCode 104

思路及实现

方式一:递归

思路

对于递归方式,我们可以将问题分解为两个子问题:左子树的最大深度和右子树的最大深度。然后,二叉树的最大深度即为左右子树最大深度中的较大值加1(根节点的深度)。递归的终止条件是当节点为空时,返回深度0。

代码实现

Java版本
// Definition for a binary tree node.
public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

public class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftDepth = maxDepth(root.left);
        int rightDepth = maxDepth(root.right);
        return Math.max(leftDepth, rightDepth) + 1;
    }
}

说明:递归函数maxDepth接收一个二叉树节点作为参数,如果节点为空,则返回深度0;否则分别计算左子树和右子树的最大深度,并返回二者中的较大值加1。

C语言版本
#include <stdio.h>
#include <stdlib.h>

// Definition for a binary tree node.
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

int maxDepth(struct TreeNode* root) {
    if (root == NULL) {
        return 0;
    }
    int leftDepth = maxDepth(root->left);
    int rightDepth = maxDepth(root->right);
    return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}

// Helper function to create a new tree node
struct TreeNode* newNode(int data) {
    struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    node->val = data;
    node->left = NULL;
    node->right = NULL;
    return(node);
}

// ... (driver code and main function)

说明:C语言版本的实现与Java版本类似,但需要注意内存分配和释放,以及节点创建函数newNode的使用。

Python3版本
# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        leftDepth = self.maxDepth(root.left)
        rightDepth = self.maxDepth(root.right)
        return max(leftDepth, rightDepth) + 1

说明:Python版本使用了类定义来构建二叉树节点,递归函数maxDepth的实现与Java版本相同。

Go语言版本
package main

import "fmt"

// Definition for a binary tree node.
type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }
    leftDepth := maxDepth(root.Left)
    rightDepth := maxDepth(root.Right)
    if leftDepth > rightDepth {
        return leftDepth + 1
    }
    return rightDepth + 1
}

func main() {
    // ... (driver code and main function)
}

说明:Go语言版本的实现也类似,只是语法稍有不同。

复杂度分析

  • 时间复杂度:O(n),其中n为二叉树的节点数。因为每个节点只被访问一次。
  • 空间复杂度:O(h),其中h为二叉树的高度。递归需要用到栈空间,最坏情况下,树完全不平衡,递归深度达到树的高度,因此空间复杂度为O(h)。但在平均情况下,由于二叉树的性质,递归调用的深度会相对较小,所以实际空间复杂度可能低于O(h)。

方式二:广度优先搜索(BFS)

思路

广度优先搜索(BFS)是另一种求解二叉树最大深度的方法。我们可以使用队列来进行层次遍历,每一层的节点数代表当前层的深度。当队列为空时,遍历结束,此时的深度即为二叉树的最大深度。

代码实现

Java版本
import java.util.LinkedList;
import java.util.Queue;

public class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        int depth = 0;
        while (!queue.isEmpty()) {
            int levelSize = queue.size();
            for (int i = 0; i < levelSize; i++) {
                TreeNode node = queue.poll();
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            depth++;
        }
        return depth;
    }
}

说明:这里使用LinkedList实现Queue接口,通过循环来逐层遍历二叉树。每遍历完一层,深度加1,直到队列为空。

C语言版本

在C语言中,没有内建的队列结构,所以我们需要手动实现一个队列。

#include <stdio.h>
#include <stdlib.h>

#define MAX_QUEUE_SIZE 100

struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

struct QueueNode {
    struct TreeNode *data;
    struct QueueNode *next;
};

struct Queue {
    struct QueueNode *front;
    struct QueueNode *rear;
};

void enqueue(struct Queue *q, struct TreeNode *node) {
    struct QueueNode *newNode = (struct QueueNode*)malloc(sizeof(struct QueueNode));
    newNode->data = node;
    newNode->next = NULL;
    if (q->rear == NULL) {
        q->front = newNode;
        q->rear = newNode;
    } else {
        q->rear->next = newNode;
        q->rear = newNode;
    }
}

struct TreeNode *dequeue(struct Queue *q) {
    if (q->front == NULL) {
        return NULL;
    }
    struct TreeNode *node = q->front->data;
    struct QueueNode *temp = q->front;
    q->front = q->front->next;
    if (q->front == NULL) {
        q->rear = NULL;
    }
    free(temp);
    return node;
}

int isQueueEmpty(struct Queue *q) {
    return q->front == NULL;
}

int maxDepth(struct TreeNode* root) {
    if (root == NULL) {
        return 0;
    }
    struct Queue q = {{NULL, NULL}};
    enqueue(&q, root);
    int depth = 0;
    while (!isQueueEmpty(&q)) {
        int levelSize = 0;
        struct TreeNode *node;
        // Count the number of nodes in current level
        while ((node = dequeue(&q)) != NULL) {
            levelSize++;
            if (node->left) {
                enqueue(&q, node->left);
            }
            if (node->right) {
                enqueue(&q, node->right);
            }
        }
        // All nodes of the current level are processed, move to the next level
        depth++;
    }
    return depth;
}

// ... (driver code and main function)

说明:在C语言中,我们需要自己实现队列的数据结构,包括入队、出队和判断队列是否为空的操作。

Python3版本
from collections import deque

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        queue = deque([root])
        depth = 0
        while queue:
            level_size = len(queue)
            for _ in range(level_size):
                node = queue.popleft()
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
            depth += 1
        return depth

说明:在Python中,我们可以使用collections.deque来实现队列,它提供了双端队列的功能,非常适合用于广度优先搜索。

复杂度分析

  • 时间复杂度:O(n),其中n是二叉树的节点数。每个节点只会被访问和入队出队一次。
  • 空间复杂度:O(n),在最坏情况下,当树完全不平衡时,所有节点都会被同时存储在队列中,因此需要额外的空间与节点数成正比。然而,在平均情况下,由于二叉树的性质,空间复杂度通常会低于O(n)。

总结:无论是递归的深度优先搜索还是非递归的广度优先搜索,它们都能有效地解决求二叉树最大深度的问题。深度优先搜索简洁直观,而广度优先搜索则更适合于层次结构的处理。在实际应用中,可以根据问题的特点和具体需求选择合适的方法。

总结

方式优点缺点时间复杂度空间复杂度
递归深度优先搜索代码直观,易于理解递归可能导致栈溢出,对于深层树效率较低O(n)O(h)
非递归深度优先搜索避免递归栈溢出,适用于深层树需要手动维护栈,代码相对复杂O(n)O(h)
广度优先搜索层次遍历,易于实现需要额外的队列空间,空间复杂度较高O(n)O(n)

相似题目

相似题目难度链接
leetcode 104 二叉树的最大深度简单力扣:力扣-104
leetcode 110 平衡二叉树简单力扣:力扣-110
leetcode 111 二叉树的最小深度简单力扣:力扣-111
leetcode 543 二叉树的直径简单力扣:力扣-543
leetcode 1654 到最近的人的最大距离中等力扣:力扣-1654

这些题目都涉及到二叉树的遍历和深度的概念,通过解决这些题目,可以加深对二叉树遍历和深度相关问题的理解和应用能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1630360.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

B站无限评论暴力截留协议及教程

B站无限评论暴力截留协议及教程 B站无限评论暴力截留协议及教程&#xff0c;需要抓CK &#xff0c;教程里面有讲如何抓取 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x 提取码&#xff1a;0b8x

PHP 错误 Unparenthesized `a ? b : c ? d : e` is not supported

最近在一个新的服务器上测试一些老代码的时候得到了类似上面的错误&#xff1a; [Thu Apr 25 07:37:34.139768 2024] [php:error] [pid 691410] [client 192.168.1.229:57183] PHP Fatal error: Unparenthesized a ? b : c ? d : e is not supported. Use either (a ? b : …

DeblurGAN-v2: Deblurring (Orders-of-Magnitude) Faster and Better

文章目录 摘要1、引言2、相关工作2.1、图像去模糊2.2、生成对抗网络 3、DeblurGAN-v2 架构3.1、特征金字塔去模糊3.2、骨干网络的选择&#xff1a;性能与效率之间的权衡3.3、双尺度RaGAN-LS判别器3.4、训练数据集 4、实验评估4.1、实现细节4.2、在GoPro数据集上的定量评估4.3、…

服务器数据恢复—存储硬盘坏道,指示灯亮黄色的数据恢复案例

服务器数据恢复环境&故障&#xff1a; 一台某品牌EqualLogic PS系列某型号存储&#xff0c;存储中有一组由16块SAS硬盘组建的RAID5磁盘阵列&#xff0c;RAID5上划分VMFS文件系统存放虚拟机文件。存储系统上层一共分了4个卷。 raid5阵列中磁盘出现故障&#xff0c;有2块硬盘…

5款文案生成器,帮你智能写作优秀文案

在当今数字化时代&#xff0c;文案写作是营销和传播领域中至关重要的一环。然而&#xff0c;对于许多人来说&#xff0c;撰写引人注目且有吸引力的文案可能是一项具有挑战性的任务。这就是为什么文案生成器变得如此受欢迎的原因。通过结合人工智能和自然语言处理技术&#xff0…

C++之STL-String

目录 一、STL简介 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 ​编辑 1.4 STL的重要性 二、String类 2.1 Sting类的简介 2.2 string之构造函数 2.3 string类对象的容量操作 2.3.1 size() 2.3.2 length() 2.3.3 capacity() 2.3.4 empty() 2.3.5 clear() 2.3.6…

JDBC查询大数据时怎么防止内存溢出-流式查询

文章目录 1.前言2.流式查询介绍3.使用流式查询3.1不开启流式查询的内存占用情况3.2开启流式查询的内存占用情况 4.开启流式查询的注意点 1.前言 在使用 JDBC 查询大数据时&#xff0c;由于 JDBC 默认将整个结果集加载到内存中&#xff0c;当查询结果集过大时&#xff0c;很容易…

【项目】YOLOv8/YOLOv5/YOLOv9半监督ssod火灾烟雾检测(YOLOv8_ssod)

假期闲来无事找到一份火灾烟雾数据集&#xff0c;自己又补充标注了一些&#xff0c;通过论文检索发现现在的火灾检测工作主要局限于对新场景的泛化性不够强&#xff0c;所以想着用半监督&#xff0c;扩充数据集的方法解决这个问题&#xff0c;所以本文结合使用现在检测精度较高…

Canal入门使用

说明&#xff1a;canal [kə’nl]&#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据订阅和消费&#xff08;官方介绍&#xff09;。一言以蔽之&#xff0c;Canal是一款实现数据同步的组件。可以实现数据库之间、数…

网络相关知识总结

1、网口设置 网口设置IP&#xff0c;即操作/etc/sysconfig/network-scripts路径下的ifcfg-xx文件 主要参数详解&#xff1a; DEVICE:网口名 ONBOOT&#xff1a;表示启动系统时是否激活网卡&#xff0c;yes为激活&#xff0c;no不激活 HWADDR:mac值 DEFROUTE://默认路由设置…

[C++基础学习]----01-C++数据类型详解

前言 C是一种静态类型的编程语言&#xff0c;它提供了丰富的数据类型来存储和操作数据。这些数据类型为C程序员提供了丰富的选择&#xff0c;可以根据具体需求来选择最合适的类型来存储和操作数据。下面详细解释一些常见的C数据类型&#xff0c;包括其原理和使用方法&#xff1…

ADOP带您科普什么是光纤网卡,它跟普通网卡有什么区别?

光纤网卡&#xff0c;也称为网络适配器或网络接口卡&#xff08;NIC&#xff09;&#xff0c;是一种用于将计算机和服务器等设备连接到数据网络的硬件设备。它通常装有一个或多个端口&#xff0c;可以通过这些端口连接不同类型的网络线缆&#xff0c;如RJ45接口的网络跳线或SFP…

云贝餐饮连锁V2-2.9.9源码

云贝餐饮连锁V2独立版、版本更新至2.9.9&#xff0c;小程序、公众号版本&#xff0c;全插件&#xff0c;公众号小程序端&#xff0c;独立版&#xff1b; 带商家端&#xff0c;修复收银台、排队点餐、堂食点餐&#xff1b;最新版更新 搭建环境教程: 系统环境&#xff1a;CentO…

Wi-Fi HaLow:重塑物联网的未来

Wi-Fi HaLow&#xff1a;引领物联网连接的革命 数字时代的蓬勃发展正在引发一场深刻的变革&#xff0c;物联网已经融入到我们的日常生活和工作中&#xff0c;成为不可或缺的一部分。随着新一代Wi-Fi技术一Wi-Fi HaLow的崭露头角&#xff0c;有望在2024年及未来&#xff0c;重新…

stm32f4单片机强制类型转换为float程序跑飞问题

如题&#xff0c;在一个数据解析函数中使用了*(float *)&data[offset]&#xff0c;其中data为uint8类型指针&#xff0c;指向的value地址为 可以看到地址0x20013A31非对齐&#xff0c;最终在执行VLDR指令时导致跑飞 VLDR需要使用对齐访问 跑飞后查看SCB寄存器发现确实是非…

磁盘未格式化,数据恢复大揭秘

一、磁盘未格式化现象概述 在日常使用电脑的过程中&#xff0c;我们有时会遇到磁盘未格式化的提示&#xff0c;这意味着我们的磁盘突然间变得不可识别&#xff0c;所有的数据和文件都似乎消失了。这种情况常常发生在外接硬盘、U盘等存储设备上&#xff0c;给我们的工作和生活带…

LC 142. 环形链表 II

142. 环形链表 II 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评…

C++ ─── 隐式类型转换、static成员、友元、内部类

目录 1. explicit关键字 2. static成员 2.1 概念 2.2 特性 3. 友元 3.1 友元函数 3.2 友元类 4. 内部类 5. 再次理解类和对象 1. explicit关键字 构造函数不仅可以构造与初始化对象&#xff0c;对于接收单个参数的构造函数&#xff0c;还具有类型转换的作用。接收单个…

基因组组装:NextDenovo2 使用大全

简介 NextDenovo 是一种针对长序列读取&#xff08;包括CLR和ONT技术&#xff09;的新型基因组组装工具。它采取了一种“先校正错误再进行组装”的方法&#xff0c;这与canu工具类似&#xff0c;但对于PacBio HiFi读取数据则无需进行校正。相较于其他工具&#xff0c;NextDenov…

使用 Vitepress 构建博客并部署到 github 平台

前言 最近写了好多篇 Chrome 浏览器插件相关的文章&#xff0c;有十几二十篇&#xff0c;就想着构建个博客&#xff0c;用来放置相应的文章。 正好前段时间看到 VitePress 1.0.0 发布了&#xff0c;而且是用 markdown 写文章&#xff0c;正好写插件文章的时候文章都是 md 格式…