LeetCode | 104.二叉树的最大深度
这次来写一下 LeetCode 的第 104 题,二叉树的最大深度。
题目描述
题目直接从 LeetCode 上截图过来,题目如下:
这也是一道关于二叉树的题目,题目中要求我们计算二叉树的最大深度,也就是从根节点到最远的叶子节点的层数。比较容易想到的方法就是对二叉树进行一次层次遍历,然后记录层数,直到遍历完所有节点,这样也就得到二叉树的最大深度。该题和 102 题的层次遍历的算法是相同的,只要在遍历的时候做计数就可以了。
题目中给出的 C++ 定义如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
}
};
题目中给出了二叉树的定义,给出了需要实现的函数的定义,我们只要实现 maxDepth 即可。
题目分析
二叉树就是每个节点最多可以有两个孩子节点,这两个孩子节点分别称为当前节点的左子树和右子树。该题目是要求计算最大深度,而题目中则写着要得到从根节点到最远叶子节点路径上的节点数量。其实题目中的描述是对题目的一个解释。
从题目来看,比较容易想到的算法就是直接使用层次进行遍历,二叉树的 层次遍历 相比于 二叉树的前序遍历、中序遍历 和 后序遍历 要稍微复杂一下。二叉树的前序遍历、中序遍历 和 后序遍历 可以简单的使用 递归 进行遍历,而 二叉树的层次遍历 则需要借助 队列 这个数据结构来完成。也就是为了遍历一种数据结构而引入了另外一种数据结构。简单的介绍一下二叉树的 层次遍历 的算法。
先来准备一个二叉树,二叉树如下图:
上图就是题目中给出的一棵二叉树,由于这棵树的深度不深,直接就可以看出有 3 层。当树比较深的时候,我们也可以用眼看、用手数。但是,计算机就不能像人这样做了,计算机需要人来写程序才能实现,需要通过一定的算法来进行计算了。我来画图演示一下对 二叉树 进行 层次遍历 的方法。
首先,需要准备一个可以充当队列的数据结构,这点很多语言都有相应的集合可以直接使用。然后从根节点开始入队,来看图。
根节点入队以后,就可以开始找根节点的 左孩子 和 右孩子 了,然后让它的 左孩子 和 右孩子 入队,并且让根节点出队,如下图。
在图中,红色表示已经 出队 的状态,绿色表示 入队 的状态。那么当前,根节点 的 左孩子 和 右孩子 入队,而 根节点 已经出队。这里为了可以直观的进行演示,队列中保存着节点的值,而实际队列中应该保存的是节点的地址,这点一定要注意。
那么,下一步,就需要让 队列 中的 节点9 和 节点20 的 左孩子 和 右孩子 也 入队。当然,节点9 是没有 左孩子 和 右孩子 的,那么将被忽略,直接让 节点20 的 左孩子 和 右孩子 入队。最后 节点9 和 节点20 需要 出队,如下图。
此时,节点20 的 左孩子 和 右孩子 都 入队 了。而 节点9 和 节点20 也 出队 了。此时就要将 节点15 和 节点7 的 左孩子 和 右孩子 进行 入队 了。但是,这两个节点都没有 左孩子 和 右孩子,因此也就没什么可入队的了,但是 节点15 和 节点7 仍然要 出队。
当 节点15 和 节点7 出队后,队列 变空了,整个 二叉树 的 层次遍历 就结束了。
上面的过程分析了 二叉树 的 层次遍历 的过程,那么 二叉树 的 深度 我们还是没有得到。其实,也已经得到了,只要我们在层次遍历的过程中,每遍历一层的时候进行一次计数就可以了。
代码实现
来具体看一下代码的实现:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int maxDepth(TreeNode* root) {
if (root == NULL) {
return 0;
}
// 队列保存树的根节点
queue<TreeNode*> que;
que.push(root);
int level = 0;
// 遍历队列
while (!que.empty()) {
queue<TreeNode*> tmp;
// 遍历每一层的节点
while (!que.empty()) {
TreeNode *p = que.front();
que.pop();
// 让当前层的左右节点入临时队
if (p->left) {
tmp.push(p->left);
}
if (p->right) {
tmp.push(p->right);
}
}
// 临时队的节点进入遍历的节点入队
while (!tmp.empty()) {
que.push(tmp.front());
tmp.pop();
}
// 记录层数
level ++;
}
return level;
}
};
提交结果
在写完 maxDepth 函数体后,点击右下角的 “执行代码”,然后观察 “输出” 和 “预期结果” 是否一致,一致的话就点击 “提交” 按钮。点击 “提交” 按钮后,系统会使用更多的测试用例来测试我们写的函数体,如果所有的测试用例都通过了,那么就会给出 “通过” 的字样,如果没有通过,会给出失败的那一组测试用例,我们继续修改代码。
- 零基础学编程034:解决一个pandas问题
- ShellExecute 启动外部程序 参数详细介绍
- 零基础学编程033:字符串的split拆分与join连接
- 零基础学编程032:生成二维码
- C#,一些非常简单但应该知道的知识点
- C#神奇的扩展方法
- 使用Python制作一个简单的刷博器
- 零基础学编程031:Python与其它语言最不同的一条语法规则
- dedecms批量导出新增文章url和标题
- 明理知意:复合索引优化及索引访问原理
- WCF配置文件与文件下载之坎坷路
- 零基础学编程030:像黑客般玩玩字符艺术
- Android获取SD卡总容量,可用大小,机身内存总容量及可用大小
- 零基础学编程029:程序员作图不用笔
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一起来学演化计算-SBX模拟二进制交叉算子和DE差分进化算子
- 通过与C++程序对比,彻底搞清楚JAVA的对象拷贝
- Spring - application.yml 数字读取错误、eg: 000001
- Swagger2 UI 提示"请确保swagger资源接口正确"解决办法
- Manytasking Jmetal 代码反向解析 2_MMDTLZ
- GitLab服务器搭建
- MATP1生成测试SolutionSet
- 以猜数字游戏引出的分治算法的理解与思考
- MATP ManyTask Multitask Problem 和 Solution 的变量范围
- Sinopia安装部署
- Nginx的405 not allowed错误解决
- Linux免密登陆
- 一起来学matlab-matlab学习笔记8 基本绘图命令_2基本绘图操作
- 用一个图书库实例搞懂二分搜索树的底层原理
- 自已做动画及编写程序搞清楚最大堆的实现原理