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

目录

  • 题目描述
  • 思路及实现
    • 方式一:递归
      • 思路
      • 代码实现
        • 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 = xself.left = Noneself.right = Noneclass Solution:def maxDepth(self, root: TreeNode) -> int:if not root:return 0leftDepth = self.maxDepth(root.left)rightDepth = self.maxDepth(root.right)return max(leftDepth, rightDepth) + 1

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

Go语言版本
package mainimport "fmt"// Definition for a binary tree node.
type TreeNode struct {Val   intLeft  *TreeNodeRight *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 100struct 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 levelwhile ((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 leveldepth++;}return depth;
}// ... (driver code and main function)

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

Python3版本
from collections import dequeclass Solution:def maxDepth(self, root: TreeNode) -> int:if not root:return 0queue = deque([root])depth = 0while 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 += 1return 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.mzph.cn/web/4466.shtml

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

相关文章

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.5

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

二叉树的创建

##根据中序和后续遍历构建二叉树 根据遍历的顺序不同构建二叉树 必须要有中序遍历的参与 BTNode* createBTree(const char* inOrder,const char* posOrder, int num) { if (num 0) { return nullptr; } BTNode* node new BTNode; node->data …

多进程编程:原理、技术与应用

title: 多进程编程&#xff1a;原理、技术与应用 date: 2024/4/26 12:14:47 updated: 2024/4/26 12:14:47 categories: 后端开发 tags: 多进程并发编程网络服务分布式系统任务处理进程池线程对比 第一章&#xff1a;进程与线程 进程与线程的概念及区别&#xff1a; 进程&am…

gitcode 上传文件报错文件太大has exceeded the upper limited size

报错 remote: Start Git Hooks Checking Error: Deny by project hooks setting ‘default’ has exceeded the upper limited size (10 MB) in commit 当前有效的解决方案 项目设置->提交设置->勾选管理员不受规则限制->提交 重新push&#xff0c;提交成功

Vitis HLS 学习笔记--IDE软件高效操作指引

目录 1. 简介 2. 实用软件操作 2.1 C/RTL Cosimulation 选项 2.2 Do not show this dialog again 2.3 New Solution 2.4 对比 Solution 2.5 以命令行方式运行&#xff08;windows&#xff09; 2.6 文本缩放快捷键 2.7 查看和修改快捷键 2.8 将Vitis HLS RTL 导入 Viv…

Oracle集群ORA-03113:end-of-file on communication channel

一、问题场景描述 今天Oracle集群要更新各数据库的数据&#xff0c;折腾的启动不了了&#xff1a; --》数据量比较大&#xff0c;数据泵方式导出的dmp文件 准备导入集群 --》由于之前的生产数据库数据比较少&#xff0c;需要增大表空间。 --》于是在sqlplus命令窗口&#xff0c…

2023年图灵奖揭晓:Avi Wigderson教授的卓越贡献

2023年图灵奖揭晓&#xff1a;Avi Wigderson教授的卓越贡献 2023年&#xff0c;图灵奖这一计算机科学领域的最高荣誉&#xff0c;颁给了普林斯顿大学的数学教授Avi Wigderson。这一决定无疑在学术界引起了广泛的关注和讨论。Avi Wigderson教授因其在理论计算机科学领域的卓越贡…

【JavaWeb】Day51.Mybatis动态SQL(一)

什么是动态SQL 在页面原型中&#xff0c;列表上方的条件是动态的&#xff0c;是可以不传递的&#xff0c;也可以只传递其中的1个或者2个或者全部。 而在我们刚才编写的SQL语句中&#xff0c;我们会看到&#xff0c;我们将三个条件直接写死了。 如果页面只传递了参数姓名name 字…

进程地址空间 【Linux】

文章目录 进程地址空间 进程地址空间 进程地址空间&#xff0c;本质是一个描述进程可视范围的大小&#xff0c; 地址空间内一定要存在各种区域划分&#xff0c;对线性地址进行start&#xff0c;和end即可 在每一个区的_start 到_end 范围内&#xff0c;这段连续的空间中&…

深入探索计算机视觉:高级主题与前沿应用的全面解析

引言 计算机视觉&#xff0c;作为人工智能领域的一个重要分支&#xff0c;旨在让计算机能够“看”懂世界&#xff0c;理解和解释视觉场景。随着深度学习技术的迅猛发展&#xff0c;计算机视觉已经在许多领域取得了显著的进展&#xff0c;如自动驾驶、安防监控、医疗诊断等。在…

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

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

刷机维修进阶教程----小米6 6x 5x机型修复基带 改写参数 改写串码实例步骤操作解析

在于众多工作室 业务接洽中有很多需要过新机的业务需求。那么大多都在机型参数和型号上面有关联。众所周知,改写机型参数为不允许的行为。操作只为解惑参数的一些常识,修复合规参数和修复手机系统为目的,请遵守国安家法律法规,今天将详细通过实例演示来解析小米6 6x 5x这些…

基于micropython和esp32cam的图像颜色识别小作品

前言 平台&#xff1a;thonny windows10 micropython esp32cam flask 0.96oled 芯片为ssd1306的0.96oled的micropython驱动&#xff1a;http://t.csdnimg.cn/T7Dn3 urequests py文件代码&#xff1a;http://t.csdnimg.cn/t4pbe conwlan.py是自己封装的连接wifi库&#xff0…

Fast-DetectGPT 无需训练的快速文本检测

本文提出了一种新的文本检测方法 ——Fast-DetectGPT&#xff0c;无需训练&#xff0c;直接使用开源小语言模型检测各种大语言模型&#xff0c;如GPT等生成的文本内容。 Fast-DetectGPT 将检测速度提高了 340 倍&#xff0c;将检测准确率相对提升了 75%&#xff0c;超过商用系…

leetcode58 最后一个单词的长度

给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大 子字符串。 示例 1&#xff1a; 输入&#xff1a;s "Hello World" 输出&#xff1…

使用yumdownloader或repotrack等工具在有网络的环境中下载所需的RPM包及其依赖项,然后将其复制到离线环境中进行安装

使用yumdownloader或repotrack等工具在有网络的环境中下载所需的RPM包及其依赖项,然后将其复制到离线环境中进行安装是一个很好的方法。以下是详细的步骤: 使用yumdownloader 安装yumdownloader: 如果系统中没有安装yumdownloader,您可以使用包管理器进行安装。例如,在基…

【中级软件设计师】上午题12-软件工程(1):软件工程模型、敏捷方法、软件需求、系统设计

上午题12-软件工程&#xff08;1&#xff09; 1 软件过程1.1 CMM 能力成熟度模型1.1 CMMI (建议直接看思维导图&#xff09; 2 软件过程模型2.1 瀑布模型2.2 增量模型2.3 演化模型2.3.1 原型模型2.3.2 螺旋模型 2.5 喷泉模型 3 统一过程&#xff08;UP&#xff09;模型4 敏捷方…

【python】利用 GridSearchCV 和 SVM 进行学生成绩预测

在机器学习领域&#xff0c;寻找最优模型参数是一个重要的步骤&#xff0c;它直接影响模型的泛化能力和预测准确性。本文将通过一个具体案例介绍如何使用支持向量机&#xff08;SVM&#xff09;和网格搜索&#xff08;GridSearchCV&#xff09;来预测学生的成绩&#xff0c;并通…

可审批可审计追溯的单网络导出文件方案,了解一下

在物理隔离状态下&#xff0c;单网络导出文件是一个重要的安全需求&#xff0c;特别是在处理敏感数据时。在这种环境下&#xff0c;数据导出需要采取特殊的安全措施&#xff0c;以确保数据传输的安全性和合规性。需要考虑以下因素&#xff1a; 安全性&#xff1a;确保传输过程加…

筛选日志并生成序列化文件

1.在idea中创建项目 selectData. 2.添加依赖&#xff0c;插件包&#xff0c;指定打包方式&#xff0c;日志文件 大家可以直接从前面项目复制。 3.本次只需要进行序列化操作&#xff0c;所以不需要Reducer模块&#xff0c;编写Mapper模块 package com.maidu.selectdata;import…