代码随想录算法训练营第十六天 | 完全二叉树

目录

  • 完全二叉树

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

完全二叉树

作者:labuladong

如何求一棵完全二叉树的节点个数呢?

// 输入一棵完全二叉树,返回节点总数
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;
}

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

判断当前节点引导的子树是不是满二叉,是的话可以直接返回子树结点数,不是的话就往下遍历。由于完全二叉树的性质,左右子树中最多只有一个子树不是满二叉。所以总体的时间复杂度仍然是logn ^ 2。

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);
}

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

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

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

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

为什么呢?原因如下:

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

在这里插入图片描述
由于完全二叉树的性质,其子树一定有一棵是满的,所以一定会触发 hl == hr,只消耗 O(logN) 的复杂度而不会继续递归。

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

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

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

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

相关文章

Camunda中强大的监听服务

文章目录 简介创建工程JavaDelegateTaskListenerExecutionListener部署发起流程CustomExecutionListener开始节点CustomExecutionListenerCustomJavaDelegateCustomExecutionListenerCustomTaskListener用户节点 ExpressionDelegate Expression流程图 简介 Camunda预览了很多接…

MTK8365安卓核心板_联发科MT8365(Genio 350)核心板规格参数

MTK8365安卓核心板是一款高性能的嵌入式处理器产品,基于联发科领先的SoC架构和先进的12纳米工艺。它集成了四核ARM Cortex-A53处理器,每个核心频率高达2.0 GHz,搭载强大的多标准视频加速器,支持高达1080p 60fps的视频解码。此外&a…

数据库(SQL)

目录 1 触发器 1.1 触发器简介 1.2 触发器的创建 语法 说明 1.3 示例 2 存储过程 2.1 什么是存储过程(函数) 2.1.1 存储过程和存储函数的区别 2.2 优势 2.3 应用场景 2.4 存储过程的创建和使用 说明 各参数类型所实现的存储过程 无参数无返…

[cmake]CMake Error: Could not create named generator Visual Studio 16 2019解决方法

配置flycv时,cmake以下代码会报错第二行的错误,网上解决方法为第三行代码 cmake .. -G "Visual Studio 16 2019 Win64" CMake Error: Could not create named generator Visual Studio 16 2019 cmake .. -G "Visual Studio 16 2019"…

【MBtiles数据格式说明】GeoServer改造Springboot番外系列一

一、MBTiles数据格式 MBTiles格式是指由MapBox制定的一种将瓦片地图数据存储到SQLite数据库中并可快速使用、管理和分享的规范,是一种用于即时使用和高效传输的规范。MBTiles既可以用作栅格输入数据存储,也可以用作WMSGetMap输出格式。规范有1.0&#xf…

C++类和对象:多态应用实例

利用多态实现计算机组转流程: polymorphic -> 多态 基础零件(抽象类): class CPU { public:virtual void calculate() 0; }; class VideoCard { public:virtual void display() 0; }; class Memory { public:virtual void…

每日算法打卡:动态求连续区间和 day 31

文章目录 原题链接题目描述输入格式输出格式数据范围输入样例:输出样例: 题目分析示例代码树状数组线段树 原题链接 1264. 动态求连续区间和 题目难度:简单 题目来源:《信息学奥赛一本通》 题目描述 给定 n 个数组成的一个数…

rp-bf:一款Windows下辅助进行ROP gadgets搜索的Rust库

关于rp-bf rp-bf是一款Windows下辅助进行ROP gadgets搜索的Rust库,该工具可以通过模拟Windows用户模式下的崩溃转储来爆破枚举ROP gadgets。 在很多系统安全测试场景中,研究人员成功劫持控制流后,通常需要将堆栈数据转移到他们所能够控制的…

第一批 Apple Vision Pro 开箱和佩戴体验新鲜出炉!!!

注: 本文转自微信公众号 BravoAI (专注AI资讯和技术分享), 原文网址:第一批 Apple Vision Pro 开箱和佩戴体验新鲜出炉!!!, 扫码关注公众号 编者按: 整个AR/VR行业都在等AVP, 期待它能带来ChatGPT般的冲击 AVP(Apple Vision Pro) 是苹果公司研发的第一款"空间计算 (Spa…

VOD-SLAM 复现 AirDos 复现

VOD-SLAM 复现 参考:https://www.mianshigee.com/project/halajun-VDO_SLAM/ 下载: git clone https://github.com/halajun/VDO_SLAM.git VDO-SLAMCSparse 库安装 sudo apt-get install libsuitesparse-dev解决:fatal error: opencv2/xfea…

基础小白快速入门python------Python程序设计结构,循环

循环在计算机中,是一个非常重要的概念,是某一块儿代码的不断重复运行,是一种逻辑思维 在编程中的体现,运用数学思维加代码结合加数据,就构成了一个循环。 在Python中,循环主要分为三大类 for循环 while循…

Revit中使用依赖注入

依赖注入的技术已经很成熟,本文主要是说明一下Revit中的适用版本与介绍相关的开源项目。 版本问题 版本 目前的依赖注入包无法支持Revit 2020 以下的版本,原因是因为包中的依赖项与Revit本身的依赖项不一致导致的,所以说如果使用Revit DI…

力扣hot100 括号生成 递归回溯 超简洁版

Problem: 22. 括号生成 Code 使用 static 会被复用 class Solution {List<String> ans new ArrayList<>();public List<String> generateParenthesis(int n){dfs(n, n, "");return ans;}/*** param l 左括号待补个数* param r 右括号待补个数*…

nodejs+vue+ElementUi电商购物个性化商城推荐系统gqfe

电本电商个性化推荐系统是为了提高用户查阅信息的效率和管理人员管理信息的工作效率&#xff0c;可以快速存储大量数据&#xff0c;还有信息检索功能&#xff0c;这大大的满足了用户和管理员这二者的需求。操作简单易懂&#xff0c;合理分析各个模块的功能&#xff0c;尽可能优…

ansible 常用命令 基本说明 个人备忘

linux下设置一台机器的名称为ansible hostnamectl set-hostname ansible //设置一台机器的名称为master-01 hostnamectl set-hostname master-01 hostnamectl set-hostname master-02 hostnamectl set-hostname node01 hostnamectl set-hostname node02 hostnamectl set-…

flutter 设置图片与文字的基线对齐

如题&#xff1a;如何实现图片和文字的基线对齐 众所周知&#xff0c;文字含有上下填充&#xff0c;这个填充是框架所给予的。 背景 在开发中&#xff0c;我当时遇到比较简单的布局&#xff0c;首先是左边图标右边文字&#xff0c;如下图所示&#xff0c; 很自然的就想到用R…

linux 使用命令创建mysql账户

目录 前言创建步骤 前言 mysql默认有一个root用户&#xff0c;这个账户权限太大了&#xff0c;用起来不太安全&#xff0c;我们通常是重新那家一个账户用于一般的数据库操作&#xff0c;下面介绍如何通过命令创建一个mysql账户。 创建步骤 登录mysql mysql -u root -p输入roo…

Unity3D正则表达式的使用

系列文章目录 unity工具 文章目录 系列文章目录前言一、匹配正整数的使用方法1-1、代码如下1-2、结果如下 二、匹配大写字母2-1、代码如下1-2、结果如下 三、Regex类3-1、Match&#xff08;&#xff09;3-2、Matches()3-3、IsMatch&#xff08;&#xff09; 四、定义正则表达式…

非内积级联学习

1.首页推荐非内积召回现状 非内积召回源是目前首页推荐最重要的召回源之一。同时非内积相比于向量化召回最终仅将user和item匹配程度表征为embeding内积&#xff0c;非内积召回仅保留item embedding&#xff0c;不构造user显式表征&#xff0c;而是通过一个打分网络计算用户-商…

CSS中的transition属性

CSS中的transition属性可以让你在一定的时间间隔内平滑地改变一个元素从一个样式到另一个样式。这个属性主要应用于以下几种CSS属性&#xff1a; 宽度&#xff08;width&#xff09;高度&#xff08;height&#xff09;背景颜色&#xff08;background-color&#xff09;颜色&…