判断二叉树是否是完全二叉树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用户和计算机控制台的我们会发现,在左侧控制台树的最上面有一个“保存的查询”,通过新建查询可以看到可以通过图形界面创建一些简单的查询操作。那么我们如果有一些特殊的查询要做要怎么来实现呢。这里我们把《查询某个时间点后…

python连接oracle数据库_深入理解Python3.6连接Oracle数据库

Python3.6连接Oracle数据库的方法详解 本文实例讲述了Python3.6连接Oracle数据库的方法。分享给大家供大家参考,具体如下: 下载cx_Oracle模块模块: https://pypi.python.org/pypi/cx_Oracle/5.2.1#downloads 这里下载的是源码进行安装 [rooto…

rfid阅读器的主要任务_RFID阅读器(读写器)的应用领域及其如何使用?

RFID阅读器(读写器)的应用领域及其如何使用?来源:本站 | 作者:admin | 发表于:2018-05-25 | 浏览次数:2181首先来了解一下RFID系统的构成:①电子标签,由芯片和标签天线组成,通过电感偶合或电磁…

计算机网络走向系统化 科学化,第六章计算机网络与INTERNET 应用习题

第六章计算机网络与Internet 应用一.是非题1.按覆盖地理范围的大小,可以吧计算机网络分为广域网,城域网。A 、对B、错2组建一局域网时,网卡不是必不可少的网络通信硬件。A、对B、错3.通信和资源共享是计算机网络最基本和最重要的特…

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

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

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

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

家用计算机来源,美计算机专家称BBS才是博客真正起源

美国计算机科学家莱斯恩斯特(Les Earnest)近日在接受国外媒体采访时表示,早在互联网面世之前,博客的原型就已经出现。恩斯特曾经在斯坦福大学计算机科学系担任高级研究科学家,目前已经退休。上世纪70年代初,他发明了计算机程序“f…

websocket底层处理粘包_Socket解决粘包问题1

粘包是指发送端发送的包速度过快,到接收端那边多包并成一个包的现象,比如发送端连续10次发送1个字符a,因为发送的速度很快,接收端可能一次就收到了10个字符aaaaaaaaaa,这就是接收端的粘包。可能我们在平时练习时没觉的…

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

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

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

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

python爬虫有学c的必要吗_可以一边学python爬虫一边学c语言吗?

数据结2113构和算法并不是一门语言,你可以说有了Python 不用5261学C或者4102C了,但是不能说不需要学数据结构了,因为它是所有语1653言的基础。看你学Python的用途,如果你学Python并不深入,或者用来日常的办公、写个小爬…

python每个字符后添加空格_python实现指定字符串补全空格的方法

有什么方法可以指定字符串长度,不够的自动补空格char定义的是一个半角字符。 当人心变成市场,当市场变成战场,战场埋葬多少理想。char[]定义的是一个不定长的数组,实际上是指针,用前要初始化。不过某些编程环境可能会根…

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

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

c位边上还有什么位_c位是什么意思?C位说法的由来是什么?c位旁边二个位置叫什么?...

今天我们要讲的词是——c位。这个词想必大家一定耳熟能详,哪怕不知道具体的含义,也多多少少听过身边的人说上那么几句。特别是在追星族或者是微博上,总能看到“c位”“c位出道”这一类的词语。所以说,c位到底是什么意思呢?C位当中…

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

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

python测开面试题_python十道经典面试题,测试你的python功底!

来源:python学习专栏 第一题,对象的类属性指向类对象class A(): def show(self): print( A_show ) class B(): def show(self): print( B_show ) obj B() obj.show() #这样我们能够正常调用 #那么我们能不能 #obj.show() #我们想调用A中的show 我们看一下…

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

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

国外计算机专业入门语言,【转自知乎】给想要报考计算机专业学生的一些建议...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼在知乎上问同类的问题较多,在学习上有困惑的同学好像还不少,我就花点时间写一下自己的看法,供在计算机领域起步的同学参考。欢迎业界高人补充和指正。1.本科应该比专科、职业学院要多一些人文类课…