判断二叉树是否是完全二叉树c语言_完全二叉树的节点数,你真的会算吗?

读完本文,你可以去力扣拿下如下题目:

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

-----------

如果让你数一下一棵普通二叉树有多少个节点,这很简单,只要在二叉树的遍历框架上加一点代码就行了。

但是,如果给你一棵完全二叉树,让你计算它的节点个数,你会不会?算法的时间复杂度是多少?这个算法的时间复杂度应该是 O(logN*logN),如果你心中的算法没有达到高效,那么本文就是给你写的。

首先要明确一下两个关于二叉树的名词「完全二叉树」和「满二叉树」。

我们说的完全二叉树如下图,每一层都是紧凑靠左排列的:

d3304f53de24c3191792cbffcb2dc0de.png

我们说的满二叉树如下图,是一种特殊的完全二叉树,每层都是是满的,像一个稳定的三角形:

0b3ab58cf041f1c42dff9c7e7353fe9f.png

说句题外话,关于这两个定义,中文语境和英文语境似乎有点区别,我们说的完全二叉树对应英文 Complete Binary Tree,没有问题。但是我们说的满二叉树对应英文 Perfect Binary Tree,而英文中的 Full Binary Tree 是指一棵二叉树的所有节点要么没有孩子节点,要么有两个孩子节点。如下:

b6b6b19ab89492b7b07adc477f44be18.png

以上定义出自 wikipedia,这里就是顺便一提,其实名词叫什么都无所谓,重要的是算法操作。本文就按我们中文的语境,记住「满二叉树」和「完全二叉树」的区别,等会会用到

一、思路分析

现在回归正题,如何求一棵完全二叉树的节点个数呢?

// 输入一棵完全二叉树,返回节点总数
int countNodes(TreeNode root);

如果是一个普通二叉树,显然只要向下面这样遍历一边即可,时间复杂度 O(N):

public int countNodes(TreeNode root) {if (root == null) return 0;return 1 + countNodes(root.left) + countNodes(root.right);
}

那如果是一棵二叉树,节点总数就和树的高度呈指数关系:

public int countNodes(TreeNode root) {int h = 0;// 计算树的高度while (root != null) {root = root.left;h++;}// 节点总数就是 2^h - 1return (int)Math.pow(2, h) - 1;
}

完全二叉树比普通二叉树特殊,但又没有满二叉树那么特殊,计算它的节点总数,可以说是普通二叉树和完全二叉树的结合版,先看代码:

public int countNodes(TreeNode root) {TreeNode l = root, r = root;// 记录左、右子树的高度int hl = 0, hr = 0;while (l != null) {l = l.left;hl++;}while (r != null) {r = r.right;hr++;}// 如果左右子树的高度相同,则是一棵满二叉树if (hl == hr) {return (int)Math.pow(2, hl) - 1;}// 如果左右高度不同,则按照普通二叉树的逻辑计算return 1 + countNodes(root.left) + countNodes(root.right);
}

结合刚才针对满二叉树和普通二叉树的算法,上面这段代码应该不难理解,就是一个结合版,但是其中降低时间复杂度的技巧是非常微妙的

PS:我认真写了 100 多篇原创,手把手刷 200 道力扣题目,全部发布在labuladong的算法小抄,持续更新。建议收藏,按照我的文章顺序刷题,掌握各种算法套路后投再入题海就如鱼得水了。

二、复杂度分析

开头说了,这个算法的时间复杂度是 O(logN*logN),这是怎么算出来的呢?

直觉感觉好像最坏情况下是 O(N*logN) 吧,因为之前的 while 需要 logN 的时间,最后要 O(N) 的时间向左右子树递归:

return 1 + countNodes(root.left) + countNodes(root.right);

关键点在于,这两个递归只有一个会真的递归下去,另一个一定会触发 hl == hr 而立即返回,不会递归下去

为什么呢?原因如下:

一棵完全二叉树的两棵子树,至少有一棵是满二叉树

29525c941b082dfaf8197c7539f8ad92.png

看图就明显了吧,由于完全二叉树的性质,其子树一定有一棵是满的,所以一定会触发 hl == hr,只消耗 O(logN) 的复杂度而不会继续递归。

综上,算法的递归深度就是树的高度 O(logN),每次递归所花费的时间就是 while 循环,需要 O(logN),所以总体的时间复杂度是 O(logN*logN)。

所以说,「完全二叉树」这个概念还是有它存在的原因的,不仅适用于数组实现二叉堆,而且连计算节点总数这种看起来简单的操作都有高效的算法实现。

_____________

我的 在线电子书 有 100 篇原创文章,手把手带刷 200 道力扣题目,建议收藏!对应的 GitHub 算法仓库 已经获得了 70k star,欢迎标星!

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

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

相关文章

怎样用计算机记账,仓管员怎么用电脑记账?简单实用的电脑操作方式一览!

仓库管理中,有很多的流水账需要进行记录,物品的收发,物品的采购等等,传统的仓库管理,多用人工方式等记录,效率相对较低,出现差错率相对较高,如今,多采用软件及电脑等方式…

免密登录关闭_微信最新提醒:这个设置再不关闭,你的微信账号就能被别人“免密登录”!...

哈喽大家好,我是你们的老朋友姗姗,每天与大家分享不一样的生活知识,阅读本文前,请您先点击上面的“姗姗时尚思”,再点击“关注”,这样您就可以继续免费收到文章了,希望可以多鼓励一下小编&#…

查看计算机用户修改密码时间,使用ldap语句查询某时间后没改密码的用户

经常使用Active Directory用户和计算机控制台的我们会发现,在左侧控制台树的最上面有一个“保存的查询”,通过新建查询可以看到可以通过图形界面创建一些简单的查询操作。那么我们如果有一些特殊的查询要做要怎么来实现呢。这里我们把《查询某个时间点后…

847方波放大电路_分析运放7大经典电路,有图有真相,详解每个电路原理!

运放的基本分析方法:虚断,虚短。对于不熟悉的运放应用电路,就使用该基本分析方法。运放是用途广泛的器件,接入适当的反馈网络,可用作精密的交流和直流放大器、有源滤波器、振荡器及电压比较器。1,运放在有源…

python实现什么功能_Python 实现WC功能

项目要求 基本要求 -c 统计文件字符数 (实现) -w 统计文件词数 (实现) -l 统计文件行数(实现) 扩展功能 -s 递归处理目录下符合条件得文件(实现) -a 返回文件代码行 / 空行 / 注释行(实现&#…

python数据处理常用函数_Python大数据处理模块Pandas

Pandas使用一个二维的数据结构DataFrame来表示表格式的数据,相比较于Numpy,Pandas可以存储混合的数据结构,同时使用NaN来表示缺失的数据,而不用像Numpy一样要手工处理缺失的数据,并且Pandas使用轴标签来表示行和列 1、…

计算机学院校友论坛,西工大计算机学院北京校友论坛成立并举办第一次活动

2021年5月16日,西北工业大学计算机学院北京校友论坛成立会议暨第一次活动在北京召开,在京计算机学院院友齐聚一堂共同研讨计算机领域新技术、新发展,共叙同窗情,共谋新未来。西北工业大学校友总会办公室副主任刘江、计算机学院院长…

邢台职业技术学院计算机系宿舍,邢台职业技术学院宿舍条件怎么样 男生女生宿舍图片...

大学马上就要开学了,邢台职业技术学院宿舍条件怎么样,有没有独立卫浴和空调,宿舍环境如何,想必是邢台职业技术学院大一新生最想知道的。小编整理了《邢台职业技术学院宿舍条件怎么样男生女生宿舍图片》一文,供大一新生…

常用计算机 启动bios,详解各种电脑开机怎么进入bios设置

开机怎么进入bios呢?电脑品牌上百种,每种品牌又有各种类型,BIOS的类型成百上千,bios设置方法也不计其数。BIOS是整个系统中最神密最难掌握的,开机怎么进入bios?bios设置方法真的是一件伤脑筋的事。针对以上的问题,小…

国服服务器_外服玩家热议LOL国服倒计时插件:说好的公平竞技呢?

对于很多国服的英雄联盟玩家来说,自从多年前各种盒子辅助软件出现之后,玩家就越来越依赖这些辅助工作所提供的便捷,虽说在过去几年间官方已经对这些功能尽量进行了简化以及遏制,但比如打野计时器、水晶计时、眼位监视等等至今仍然…

int转unsigned int_谢劲课题组在基于锰催化的转金属化基元反应取得系列进展

本文来自微信公众号:X-MOLNews用廉价的过渡金属催化剂替代贵金属催化剂是解决未来自然资源问题紧缺的一个很好选择。锰是地壳中含量排第三位的过渡金属,价格便宜,环境危害小。但由于其较低的催化活性,锰催化参与的许多金属有机化学…

pip更换镜像源_Ubuntu20.04LTS更换软件源镜像

我用的是Linux的Windows子系统下的Ubuntu20.04LTS版本,这个版本很重要!首先是备份一下开始的源打开位置/etc/apt/sources.list备份sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后删除掉sources.listsudo rm /etc/apt/sources.list在目录 …

云教版认识计算机说课,【教学设计】第1册第1课《认识电脑交朋友》

备课时间:2017年9月3日一、教材分析本节课是省编最新版《小学信息技术》教材第一册第一课。“学一学”由三个部分组成:探寻电脑应用技术;了解电脑组成;养成良好习惯。这三个部分的知识,不仅拓展了学生的视野&#xff0…

cdn需要备案吗_车子贴改色膜需要到车管所备案吗?

改色膜至今为止已经流行很多年了,但还是有部分车主对于贴改色膜之后备案这个事情还不是很了解,对于这个就来点知识小科普吧~~首先汽车贴改色膜是合法的,但这个也是有前提的,首先汽车车身更换颜色超过30%的话,就需要到车…

mysql数据库中文显示_关于Mysql数据库中文显示问题

挣扎在初级Web开发,无论是hibernate还是基础的jdbc都要涉及到一个编码问题,毕竟编程这套东西是伦家外国银发明的,我大中华的程序猿不得不低头,闲言少叙。严明而言,3点:1.mysql配置文件my.ini中添加2条&…

读算法霸权笔记03_操控与恐吓

1. 市场失灵 1.1. 探索市场失灵现象就像寻宝游戏,很有意思 1.2. 建立一种算法来预测这个循环出现差错——多找回的两枚硬币——的可能性并对此下注 1.2.1. 盈利模式消失了,或者市场中的其他人也了解了这个模式,先行者优势消失 1.3. 在很多…

win10看计算机属性,win10系统查看windows7版本号要比计算机属性具体的图文步骤

win10系统使用久了,好多网友反馈说关于对win10系统查看windows7版本号要比计算机属性具体设置的方法,在使用win10系统的过程中经常不知道如何去对win10系统查看windows7版本号要比计算机属性具体进行设置,有什么好的办法去设置win10系统查看w…

myeclipse怎么创建jframe类_创建型-建造者模式

一个对象创建的时候,需要各种初始化化,有一套复杂的创建流程,如果这些流程散布在系统各个地方的话,会越来越难以维护,因此建造者模式就是把一套复杂的创建某个具体产品的流程,管理起来。定义:将…

mysql占用内存吗_mysql占多少内存

展开全部MySQL 自身内存规62616964757a686964616fe4b893e5b19e31333433646463划说到 MySQL 自身的内存规划,最先想到的就是 MySQL 中各种 buffer 的大小,innodb buffer pool 就是最鹤立鸡群的那个。innodb_buffer_pool_size 参数的大小究竟如何设置&…

计算机鼠标装有,计算机鼠标装有传感器来监视鼠标的移动情况,如图

利用欧姆定律进行计算:根据串、并联电路的特点和欧姆定律的公式可进行有关计算。解题的方法是:(1)根据题意画出电路图,看清电路的组成(串联还是并联);(2)明确题目给出的已知条件与未知条件,并在电路图上标明&#xff1…