代码随想录算法训练营day16

题目:104.二叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

参考链接:代码随想录

104.二叉树的最大深度

思路:上次是用层序遍历的思路做过。这次想一点不一样的思路,对于一个二叉树的最大深度其实即为其两个子树的最大深度+1,所以可以采用递归法解决,结束条件即当root都为空的时候,最大深度即为1。时间复杂度O(n)。

class Solution {
public:int maxDepth(TreeNode* root) {if(!root){return 0;}return max(maxDepth(root->left),maxDepth(root->right))+1;}
};

可以看到递归法的代码非常简单,但是运行时间比层序遍历长一些。看完解析后认识到这种方法实际上采用的是后续遍历。
真正求深度的逻辑应该采用前序遍历,即从上往下求,按照中->左->右的顺序。
代码如下:

class Solution {
public:int result;void getdepth(TreeNode* root,int depth){result=max(result,depth);//更新最大深度,每次遍历都和当前深度比较if(root->left){getdepth(root->left,depth+1);}if(root->right){getdepth(root->right,depth+1);}return;}int maxDepth(TreeNode* root) {if(!root){return 0;}result=0;getdepth(root,1);return result;}
};

111.二叉树的最小深度

思路:之前也用过层序遍历的方法。想想递归法,首先最小深度和最大深度不一样,主要是当左右节点只有一个节点为空的时候,需要直接不考虑这个节点,考虑另一半仅有的节点,而当左右孩子都空,则直接返回1,左右孩子都满,需要取左右最小值后加一。这里需要分三类讨论:左右为空,左右一个空,左右都不空。故一开始就要把根节点是否为空单独考虑。

class Solution {
public:int mD(TreeNode* root,int depth){//此时root不为空,depth为此时最小深度int result=depth;if(!root->left&& !root->right){//两边空,最小深度为1result=1;}else if(!root->left){//左边为空result=mD(root->right,result)+1;//只算右边}else if(!root->right){//右边为空result=mD(root->left,result)+1;//只算左边}else{//两边都有result=min(mD(root->left,result),mD(root->right,result))+1;//算两边后去最小值}return result;}int minDepth(TreeNode* root) {if(!root){return 0;}return mD(root,1);}
};

这种写法实际上是前序遍历,采用的回溯法。看了标答后,发现可以把子函数getdepth写成void返回值,将计算的结果单独写成一个全局变量 result ,这样就不需要递归中每次调用函数都返回一个result,在getdepth逐渐调用的过程中全局变量也就完成了计算,节约了空间复杂度。
前序遍历标答:(自己写的)

class Solution {
public:int result;void getdepth(TreeNode* root,int depth){//此时root不为空,depth为此时深度if(!root->left&& !root->right){//两边空,叶子节点返回result=result<depth ? result : depth;}if(root->left){//左边getdepth(root->left,depth+1);}if(root->right){//右边getdepth(root->right,depth+1);}return;}int minDepth(TreeNode* root) {if(!root){return 0;}result=INT_MAX;getdepth(root,1);return result;}
};

标答和自己写的其实有很大区别,没有将两边孩子都不空的时候单独考虑,而是分别考虑左右孩子,只要不为空,则将深度+1后开始计算孩子子树,计算result的时机就是已经到达叶子节点,此时只需要将result和当前遍历的深度比较即可,没有左右子树的比较,result是在前序遍历中逐渐减小的
后序遍历标答:

class Solution {
public:int minDepth(TreeNode* root) {if(!root){return 0;}int minLeftDepth=minDepth(root->left);//计算左右子树int minRightDepth=minDepth(root->right);if(root->left&&!root->right){//右空return minLeftDepth+1;}if(!root->left&&root->right){//左空return minRightDepth+1;}return min(minLeftDepth,minRightDepth)+1;}
};

后续遍历我一开始没想到,实际上自己写的时候没仔细想是什么遍历。这个答案是比较标准的写法,将左右子树的答案都保存下来,如此递归,然后对左右子树分类讨论而最大深度则不需要分类讨论,这是两题的最大区别。

222.完全二叉树的节点个数

思路:本题一开始最简单的思路就是直接遍历,使用什么方法都可以,然后计数,这对所有普通二叉树都适用。普通方法,一是层次遍历计数,二是类似求深度的写法进行递归,实际上都是遍历方法。所有遍历时间复杂度都是O(n)
层次遍历:

class Solution {
public:int countNodes(TreeNode* root) {queue<TreeNode*> q;int count=0;if(root){q.push(root);}while(!q.empty()){int size=q.size();for(int i=0;i<size;i++){TreeNode* node=q.front();q.pop();if(node->left){q.push(node->left);}if(node->right){q.push(node->right);}count++;}}return count;}
};

递归:

class Solution {
public:int countNodes(TreeNode* root) {if(!root){return 0;}return 1+countNodes(root->left)+countNodes(root->right);}
};

上面两种方法是通用方法。我们需要利用完全二叉树的性质,看能不能降低一点时间复杂度。这里想了很久没想出来,直接看了解析。首先,要利用完全二叉树的特性,分为两种,一种是满二叉树,对于完全二叉树的满二叉树可以根据一直往左遍历和一直往右遍历深度是否相等来判断;对于非满二叉树,其左右孩子一直遍历,一定会遇到左右子树都是满二叉树的情况。如图所示:可以将一个非满二叉树分解为多个二叉树,使用递归求解。满二叉树的节点个数为2^depth-1。
在这里插入图片描述

class Solution {
public:int countNodes(TreeNode* root) {if(!root) return 0;int leftDepth=0;int rightDepth=0;TreeNode* tmp=root;while(tmp){//计算左深度tmp=tmp->left;leftDepth++;}tmp=root;while(tmp){//右深度tmp=tmp->right;rightDepth++;}if(leftDepth==rightDepth){//是满二叉树return pow(2,leftDepth)-1;}else{return 1+countNodes(root->left)+countNodes(root->right);}}
};

时间复杂度O(logn*logn),前一个logn是计算左右深度,后一个为递归深度。

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

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

相关文章

【Python机器学习】详解Python机器学习进行时间序列预测

&#x1f517; 运行环境&#xff1a;Python &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 &#x1f510;#### 防伪水印——左手の明天 ####&#x1f510; &#x1f497; 大家…

C++:const关键字

一、const成员变量(常成员变量) 1、只能使用初始化列表对常成员变量进行初始化&#xff1b; 2、常成员变量可以被访问&#xff0c;但是不能被修改&#xff1b; 3、类中所有构造函数都必须在初始化列表对常成员函数进行初始化(包括拷贝构造&#xff0c;移动构造)。 声明&am…

加固平板电脑在无人机的应用|亿道三防onerugged

无人机技术的快速发展已经在许多领域展现出巨大潜力&#xff0c;而加固平板电脑的应用在无人机领域中扮演着重要角色。 首先&#xff0c;加固平板电脑在无人机探测设备中发挥着关键作用。无人机探测设备通常需要实时传输高清图像和数据&#xff0c;以支持各种监测、勘测和检测…

蓝桥杯DP算法——背包问题(C++)

目录 一、01背包问题 二、完全背包问题 三、多重背包问题 四、多重背包问题&#xff08;优化版&#xff09; 五、分组背包问题 一、01背包问题 01背包问题就是有N件物品&#xff0c;一个空间大小为V的背包&#xff0c;每个物品只能使用一次&#xff0c;使得背包中所装物品…

职场数据分析必备|数据库入门之可视化工具Navicat

1、下载 Navicat &#xff08;1&#xff09;官网下载&#xff1a;https://navicatformysql.en.softonic.com/download 下载图示&#xff1a; 数据库入门&#xff08;二&#xff09;可视化工具Navicat​mp.weixin.qq.com/s?__bizMzU3Mzk0OTIzNA&mid100001258&idx1&…

el-table实现嵌套表格的展示

需求 一个表单中存在子表 列表返回格式 实现 实现思路 el-table中在嵌套一个el-table&#xff0c;这样数据格式就没问题了&#xff0c;主要就是样式 将共同的列放到一列中&#xff0c;通过渲染自定义表头render-header&#xff0c;将表头按照合适的宽度渲染出来 <el-…

品牌如何做好话题营销?这三点很关键

从“野性消费”到“疯四文学”&#xff0c;这些品牌让人记住的并不是某个内容&#xff0c;而是一个社交谈资&#xff0c;这些都算是成功的品牌话题&#xff0c;品牌话题的优势在于激活品牌&#xff0c;始终保持品牌活力&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;品牌…

免费3D模型网站大盘点,你推荐哪一个?

越来越多的设计师开始使用3D模型来提高效率、降低成本、提升效果和用户体验等。然而&#xff0c;寻找高质量的免费3D模型网站并不是一件容易的事情。今天&#xff0c;我们就来为大家介绍一些优秀的免费3D模型网站。 一、建e网 建e网是一个专业的室内设计资源平台&#xff0c;为…

Java的Lock(二)

自旋锁 VS 适应性自旋锁 堵塞或者notify一个Java线程需要操作系统切换CPU状态来完成(详情请参考11408)。这种状态切换需要耗费CPU时间。如果同步代码块种的内容过于简单。状态切换消耗的时间可能比用户代码执行的时间还要长。 在许多场景中,同步资源的锁定时间很短,为了这一…

初识aurora

高速接口 传输速率达到Gbit/s 硬件上的高速接口 SFP VPX FMC等 软件上的高速接口 高速接口的IP核 &#xff0c;起到串并转换等作用 &#xff0c;一般高速接口就调用IP核 auroraIP核 将有效数据打包成aurora帧格式再通过gt收发器传输出去 &#xff0c;一般用在两个fpga之…

电子防潮柜如何应对潮湿问题?

智能化时代的到来&#xff0c;让电子产品成为人们生活中的必需品&#xff0c;电子产品对存储环境的要求非常高。潮湿会产生发霉、生锈、氧化、腐蚀、变形等现象&#xff0c;缩短了电子产品的寿命。绝大部分电子产品都要求在清洁低湿干燥的环境中存放&#xff0c;环境中的温湿度…

【每周AI简讯】OpenAI推出王炸文生视频模型Sora

ChatGPT中文版https://ai7.pro OpenAI推出王炸文生视频模型Sora OpenAI 宣布推出名为 Sora 的新型文本到视频模型。Sora 能根据用户的文本提示&#xff0c;生成长达一分钟的逼真视频。它可以创造出细节丰富的场景、复杂的摄影机运动以及表情丰富的多个角色。Sora 是一种扩散模…

提取游戏音频文件.bnk

提取游戏音频文件.bnk 什么是.bnk准备Wwise-Unpacker工具使用Wwise-Unpacker工具总结 什么是.bnk .bnk其实是一种对音频的加密方式&#xff0c;一个.bnk文件中通常包含了多个语音文件&#xff0c;一般可以使用Wwise-Unpacker来解码.bnk格式文件 准备Wwise-Unpacker工具 Wwis…

网络原理 - HTTP/HTTPS(3)

HTTP请求 认识请求"报头" header的整体的格式也是"键值对"的结构. 每个键值对占一行,键和值之间使用分号进行分割. 报头的种类有很多,此处仅介绍几个常见的. Host 表示服务器主机的地址和端口.(Host和URL中的ip地址端口啥的,绝大部分情况下都是一样的,少…

解决Ubuntu中vscode右键没有create catkin package

右键发现没有这个create catkin package 解决方案&#xff1a; 查了一会发现安装个拓展就可以了 效果&#xff1a;

xilinx除法器的使用

平台&#xff1a;Vivado2018.3. 芯片&#xff1a;xcku115-flva1517-2-i (active) 最近学习使用了xilinx除法器&#xff0c;在使用过程中出现了很多次除法器的结果和我预计的结果不一致&#xff0c;特此记录学习一下。 参考文件&#xff1a;pg151.下载地址 pg151-div-gen.pdf …

【linux】查看openssl程序的安装情况

【linux】查看openssl程序的安装情况 1、查看安装包信息 $ rpm -qa |grep openssl 2、安装路径 $ rpm -ql openssl $ rpm -ql openssl-libs $ rpm -ql openssl-devel 3、相关文件和目录 /usr/bin/openssl /usr/include/openssl /usr/lib64/libssl.so.* /usr/lib64/libcrypto…

uniapp项目准备工作

1.封装请求 export const baseUrl function getHeaders () {let token uni.getStorageSync(token)let header {"access-token":token,// X-Requested-With: XMLHttpRequest,Content-Type: application/json; charsetUTF-8}return header } function reLogin(){/…

Filezilla 银河麒麟桌面操作系统V10(sp1)与Windows主机数据传输问题

银河麒麟桌面操作系统V10&#xff08;sp1&#xff09;与Windows主机数据传输问题 1. 关闭Windows主机的防火墙和KylinOS V10的防火墙 如果不知道怎么关闭的参考这两篇文章&#xff1a; https://blog.csdn.net/m0_70885101/article/details/127271517 https://blog.csdn.net/w…

扫盲:什么是webGPU,和webGL对比哪些优点?

web端的3D图像渲染&#xff0c;大都采用webGL&#xff0c;不过其性能让大家很崩溃&#xff0c;webGPU的出现&#xff0c;让大家看到了访问加速的可能&#xff0c;本文通过对比webGPU与webGL&#xff0c;给老铁们普及一下。老铁们如有数据可视化的设计和开发需求&#xff0c;可以…