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

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

示例 1:

输入:root = [1,2,3,4,5,6]
输出:6
示例 2:

输入:root = []
输出:0
示例 3:

输入:root = [1]
输出:1

提示:

树中节点的数目范围是[0, 5 * 104]
0 <= Node.val <= 5 * 104
题目数据保证输入的树是 完全二叉树

进阶:遍历树来统计节点是一种时间复杂度为 O(n) 的简单解决方案。你可以设计一个更快的算法吗?

法一:直接递归模拟:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int countNodes(TreeNode* root) {int ans = 0;findAns(root, ans);return ans;}private:void findAns(TreeNode *node, int &ans){if (node == nullptr){return;}++ans;findAns(node->left, ans);findAns(node->right, ans);}
};

如果树中有n个节点,此算法时间复杂度为O(n),空间复杂度为O(logn)。

法二:手动模拟一个栈,中序遍历:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int countNodes(TreeNode* root) {stack<TreeNode *> s;s.push(root);int ans = 0;while (!s.empty()){TreeNode *curNode = s.top();s.pop();if (curNode){++ans;s.push(curNode->left);s.push(curNode->right);}}return ans;}
};

如果树中有n个节点,此算法时间复杂度为O(n),空间复杂度为O(logn)。

法三:Morris中序遍历:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int countNodes(TreeNode* root) {int ans = 0;TreeNode *curNode = root;while (curNode){if (curNode->left == nullptr){++ans;curNode = curNode->right;continue;}TreeNode *mostRightOfLeft = getMostRightOfLeft(curNode);if (mostRightOfLeft->right == nullptr){mostRightOfLeft->right = curNode;curNode = curNode->left;}else if (mostRightOfLeft->right == curNode){++ans;mostRightOfLeft->right = nullptr;curNode = curNode->right;}    }return ans;}private:TreeNode *getMostRightOfLeft(TreeNode *node){TreeNode *curNode = node->left;while (curNode->right && curNode->right != node){curNode = curNode->right;}return curNode;}
};

如果树中有n个节点,此算法时间复杂度为O(n),空间复杂度为O(1)。

法四:层序遍历:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int countNodes(TreeNode* root) {deque<TreeNode *> dq;dq.push_back(root);int ans = 0;while (!dq.empty()){TreeNode *node = dq.front();dq.pop_front();if (node){++ans;if (node->left){dq.push_back(node->left);}if (node->right){dq.push_back(node->right);}}}return ans;}
};

如果树中有n个节点,此算法时间复杂度为O(n),空间复杂度为O(logn)。

法五:利用完全二叉树的特点,完全二叉树除了最后一层外,其他层都是满节点的,因此我们可以先计算出除最后一层外的所有层的节点数,然后利用二分法,找到最后一层的节点数:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int countNodes(TreeNode* root) {if (root == nullptr){return 0;}int h = 0;TreeNode *curNode = root;while (curNode){++h;curNode = curNode->left;}int left = 0;int right = (1 << (h - 1)) - 1;int bottomNum = 0;while (left <= right){TreeNode *curNode = root;int mid = (left + right) / 2;for (int i = h - 2; i >= 0; --i){if ((1 << i) & mid){curNode = curNode->right;}else{curNode = curNode->left;}}if (curNode == nullptr){right = mid - 1;}else{bottomNum = mid;left = mid + 1;}}return pow(2, h - 1) + bottomNum;}
};

如果树中有n个节点,此算法时间复杂度为O(lg 2 ^2 2n),找出树的高度需要logn的时间,对于二分的外层循环需要logn的时间,每次二分查找需要logn的时间来确定是否有叶子节点;空间复杂度为O(1)。

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

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

相关文章

Hack The Box-Analytics

目录 信息收集 namp whatweb WEB 信息收集 feroxbuster RCE漏洞 提权 get user get root 信息收集 namp 端口信息探测┌──(root㉿ru)-[~/kali/hackthebox] └─# nmap -p- 10.10.11.233 --min-rate 10000 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-…

python adb脚本

Python调用adb shell ls&#xff0c;取前5个字符存放&#xff0c;并打印出来 import subprocess def run_adb_shell_command(command):# 设置adb的路径&#xff0c;根据您的实际情况进行修改 adb_path adb # 使用subprocess运行adb shell命令&#xff0c;并捕获输出 resu…

Python面向对象——架构设计【2】

练习1&#xff1a;打电话 请使用面向对象思想描述下列情景: 小明使用手机打电话,还有可能使用座机.... class People:def __init__(self,name):self.name namedef call_up(self,tool):print(self.name,end"")tool.call()class Tools:def __init__(self,way):self.wa…

OpenCV(八)——基本线条操作

基本线条操作 OpenCV中提供了基本的线条的操作&#xff0c;包括画直线、画矩形、画圆形等。 &#xff08;1&#xff09;画直线&#xff0c;在OpenCV中利用line()画直线&#xff0c;形式为image_with_line cv2.line(image, start_point, end_point, color, thickness)。line(…

智慧矿山新趋势:大数据解决方案一览

1. 背景 随着信息技术的快速发展和矿山管理需求的日益迫切&#xff0c;智慧矿山作为一种创新的矿山管理方式应运而生。智慧矿山借助先进的信息技术&#xff0c;实现对矿山生产、管理、安全等各方面的智能化、高效化、协同化&#xff0c;是矿山行业转型升级的必然趋势。 欢迎关…

Java 容器都有哪些?

Java容器是Java编程语言中用于存储和组织对象的数据结构。在Java中&#xff0c;容器类库提供了各种类型的容器&#xff0c;每种容器都有其特定的用途和适用场景。 1. 数组&#xff08;Array&#xff09; 数组是Java中最基本的容器类型之一&#xff0c;用于存储相同数据类型的…

【LabVIEW FPGA入门】并行执行

利用图形化编程的并行特性以及 FPGA 上 LabVIEW 图的真正并行实现&#xff0c;您可以通过将应用程序代码划分为更小的进程来进一步优化执行速度。与整个应用程序在一个循环中运行相比&#xff0c;这使得每个进程能够实现更高的循环速率和更高的应用程序整体执行速率。 …

Java语法学习八之认识String类

String类的重要性 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以使用标准库提供的字符串系列函数完成大部分操作&#xff0c;但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想&#xff0c;而…

C++开发基础——函数模板

一&#xff0c;函数模板 1.基础概念 模板编程是C中泛型编程的基础。 一个模板可以是创建类或者函数的蓝图。 模板编程分两种&#xff0c;分别是算法抽象的模板、数据抽象的模板。算法抽象的模板以函数模板为主&#xff0c;数据抽象的模板以类模板为主。 基于函数模板生成的…

Vue面试题,背就完事了

1.vue的生命周期有哪些及每个生命周期做了什么? Vue.js 的生命周期可以分为以下几个核心阶段&#xff0c;每个阶段都伴随着特定的钩子函数&#xff08;生命周期钩子&#xff09;来执行相应的操作&#xff1a; 创建阶段&#xff1a; beforeCreate&#xff1a;实例被创建后、数…

13.Python从入门到精通—Python 集合操作与方法概览

13.Python从入门到精通—Python 集合操作与方法概览 Python 集合集合的基本操作1、添加元素2、移除元素3、计算集合元素个数4、清空集合5、判断元素是否在集合中存在 集合内置方法完整列表 Python 集合 在Python中&#xff0c;集合是一种无序、不重复的数据类型。集合通常用于…

MVC接收请求教程

mvc接收各种请求 1-环境搭建 1.1-准备apifox发送请求 1.2-项目搭建 ①创建Web骨架的Maven项目 ​ --打开2023-IDEA &#xff0c;选择New Project ​ --选择Maven Archetype ​ --注意点&#xff1a;Catalog默认就行了 ​ --Archetype选择webapp ​ --JDK跟着黑马敲最好…

无需借助任何三方软件,使用Windows自带分区功能实现磁盘分区!

像上面截图那样,如果当你由于文件分类或磁盘容量,想增加或减少分区盘符该怎么办。简单的理解就是怎么从E盘再分出个F盘,或者怎么从E盘分出点空间把D盘空间增大。 这里就牵扯出一个概念,磁盘分区,大概意思就是把一整个物理磁盘在系统上分出好几块区域,用来存放不同的文件…

【C++练级之路】【Lv.14】二叉搜索树(进化的二叉树——BST)

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《C语言》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、二叉搜索树介绍二、二叉搜索树的模拟实现2.1 结点2.2 成员变量2.3 默认成员函数2.3.1 constructor2.3.2…

7 Internet基础(2)

1.分片控制 在 IP 数据报报头中&#xff0c;标识、标志和片偏移3 个字段与控制分片和重组有关。 标识&#xff1a;是源主机赋予 IP 数据报的标识符。目的主机利用此域和目的地址判断收到的分片属于哪个数据报&#xff0c;以便数据报重组。分片时&#xff0c;该域必须不…

sql语句基础语法之 数据表的添加相关 ​字段相关操作 ​数据筛选相关操作 ​数据排序相关操作 ​聚合函数

3月18日 数据表的筛选数据&#xff0c;字段操作&#xff0c;聚合函数 内容如下&#xff1a; ​ 数据表的添加相关 ​ 字段相关操作 ​ 数据筛选相关操作 ​ 数据排序相关操作 ​ 聚合函数 数据表的添加相关 use mydb; create table class_img (id int unique key auto_…

Springboot笔记-01

简化spring应用开发&#xff0c;约定大于配置 简化Spring应用开发的一个框架&#xff1b; 整个Spring技术栈的一个大整合&#xff1b; J2EE开发的一站式解决方案&#xff1b; 优点&#xff1a; 快速创建独立运行的spring项目以及于主流框架集成 使用嵌入式的Servlet容器&#x…

IonQ最新研究突破!引入光量子纠缠以构建量子计算网络

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨沛贤 深度好文&#xff1a;700字丨5分钟阅读 2024年2月22日&#xff0c;美国量子计算公司IonQ宣布&#xff0c;公司研究团队已实现可重复地生成与离子纠缠的光子&#…

目标检测——YOLOv4算法解读

论文&#xff1a;YOLOv4&#xff1a;Optimal Speed and Accuracy of Object Detection 作者&#xff1a;Alexey Bochkovskiy, Chien-Yao Wang, Hong-Yuan Mark Liao 链接&#xff1a;https://arxiv.org/pdf/2004.10934.pdf 代码&#xff1a;https://github.com/AlexeyAB/darkne…

如何使用Excel进行设备管理:巡检、维修、保养、备件管理

在现代企业运营中&#xff0c;设备管理是维持生产效率和保障生产安全的关键环节。良好的设备管理包括设备的巡检、维修、保养和备件管理等多个方面。随着信息技术的发展&#xff0c;许多企业开始利用电子化工具来提高设备管理的效率和准确性。其中&#xff0c;Excel作为一款功能…