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

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

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

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

示例 1:

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

示例 2:

输入: root = []
输出: 0

示例 3:

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

提示:

  • 树中节点的数目范围是 [ 0 , 5 × 1 0 4 ] [0, 5 \times 10^4] [0,5×104]
  • 0 ≤ N o d e . v a l ≤ 5 ∗ 104 0 \leq Node.val \leq 5 * 104 0Node.val5104
  • 题目数据保证输入的树是 完全二叉树

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

解法一(统一迭代遍历)

思路分析:

  1. 采用统一迭代二叉树的遍历方法,来对二叉树进行遍历,在遍历的过程中统计节点数目

  2. 此处采用 前序遍历

实现代码如下:

class Solution {public int countNodes(TreeNode root) {int ans = 0;if (root == null)return ans;		// 边界条件Deque<TreeNode> stack = new LinkedList<>();stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();if (node != null) {// 对节点进行处理 添加待遍历节点if (node.right != null)stack.push(node.right);if (node.left != null)stack.push(node.left);// 添加待处理节点stack.push(node);stack.push(null);	// 使用null标记待处理节点} else {stack.pop();	// 弹出待处理节点++ ans;		// 对节点进行计数}}return ans;}}return ans;}
}

提交结果如下:

解答成功:
执行耗时:9 ms,击败了5.25% 的Java用户
内存消耗:44.5 MB,击败了83.97% 的Java用户

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

解法二(BFS+队列)

思路分析:

  1. 采用层序遍历法,对二叉树进行遍历,并在遍历过程中 统计节点数

实现代码如下:

class Solution {// BFSpublic int countNodes(TreeNode root) {int ans = 0;if (root == null)return ans;		// 边界条件Queue<TreeNode> queue = new ArrayDeque<>();queue.offer(root);while (!queue.isEmpty()) {int size = queue.size();for (int i = 0; i < size; ++i) {++ ans;TreeNode node = queue.poll();if (node.left != null) queue.offer(node.left);if (node.right != null) queue.offer(node.right);}}return ans;}
}

提交结果如下:

解答成功:
执行耗时:5 ms,击败了9.04% 的Java用户
内存消耗:46.5 MB,击败了5.07% 的Java用户

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

解法三(二分查找+位运算)

思路分析:

  1. 首先题目给出该二叉树为 完全二叉树,因此可以利用完全二叉树的特性计算节点个数。

  2. 首先规定根节点位于第0层,完全二叉树的最大层数为h,且根据完全二叉树的特性有;最左边的节点一定位于最底层,且从根节点到最左边的节点的路径长度即为最大层数h

  3. 0 ≤ i < h 0 \leq i < h 0i<h时,第i层包含 2 i 2^i 2i个节点,最底层包含节点数最少为1,最多为 2 h 2^h 2h

    1. 当底层包含1个节点时,完全二叉树的节点个数是: ∑ i = 0 h − 1 2 i + 1 = 2 h \sum_{i=0}^{h-1}2^i+1 = 2^h i=0h12i+1=2h

    2. 当底层包含 2 h 2^h 2h个节点时,完全二叉树的节点个数时: ∑ i = 0 h = 2 h + 1 − 1 \sum_{i=0}^{h} = 2^{h+1} - 1 i=0h=2h+11

  4. 因此对于最大层数为h的完全二叉树,节点个数在 [ 2 h , 2 h + 1 − 1 ] [2^h, 2^{h+1}-1] [2h,2h+11]的范围内,即在该范围内通过二分查找的方式得到完全二叉树的节点个数

  5. 即根据节点个数范围的上下界得到判断的节点个数k,如果第k个节点存在,则节点个数一定大于或等于k,如果第k个节点不存在,则节点个数一定小于 k,因此每次查找的范围缩小一半,直到找到节点个数。

  6. 如何判断第k个节点是否存在?如果第k个节点位于第h层,则k的二进制表示包含h+1位,且最高位为1其余各位从高到底表示从根节点到第k个节点的路径0表示移动到左子节点,1表示移动到右子节点

  7. 通过位运算得到第k个节点对应的路径,然后判断该路径对应的节点是否存在,则可判断第k个节点是否存在

实现代码如下:

class Solution {// 二分查找 + 位运算public int countNodes(TreeNode root) {if (root == null) return 0;	// 边界// 获取二叉树的层数int h = 0;TreeNode node = root;while (node.left != null) {++ h;	// 计算二叉树的层数node = node.left;}// 根据二叉树的层数 获取节点数范围int min = 1 << h;	// 位运算计算	最低限度int max = (1 << (h + 1)) - 1;	// 位运算计算 最高限度int ans = 0;	// 即二分查找寻找符合条件的 用ans来保存// 二分查找区间为 左闭右闭while (min <= max) {int mid = ((max - min) >> 1) + min;if (exitTreeNode(mid, root, h)) {// 如果存在 则继续查找ans = mid;min = mid + 1;} else {max = mid - 1;}}return ans;		// 在结束二分查找时 min指向的节点是最后一个存在的节点}private boolean exitTreeNode(int k, TreeNode root, int level) {// 获取当前从根节点出发的方向int bits = 1 << (level-1);TreeNode node = root;while (node != null && bits > 0) {if ((bits & k) == 0) {node = node.left;} else {node = node.right;}bits >>= 1;}return node != null;}
}

提交结果如下:

解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:46.4 MB,击败了8.84% 的Java用户

复杂度分析:

  • 时间复杂度: O ( l o g 2 n ) O(log^{2}_{}{n}) O(log2n)n为完全二叉树的节点数
  • 空间复杂度: O ( 1 ) O(1) O(1),只使用有限的额外空间

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

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

相关文章

解决沁恒ch592单片机在tmos中使用USB总线时,接入USB Hub无法枚举频繁Reset的问题

开发产品时采用了沁恒ch592&#xff0c;做USB开发时遇到了一个奇葩的无法枚举问题。 典型症状 使用USB线直连电脑时没有问题&#xff0c;可以正常使用。 如果接入某些特定方案的USB Hub&#xff08;例如GL3510、GL3520&#xff09;&#xff0c;可能会出现以下2种情况&#xf…

2024年第八届人工智能与虚拟现实国际会议(AIVR 2024)即将召开!

2024年第八届人工智能与虚拟现实国际会议&#xff08;AIVR 2024&#xff09;将2024年7月19-21日在日本福冈举行。人工智能与虚拟现实的发展对推动科技进步、促进经济发展、提升人类生活质量等具有重要意义。AIVR 2024将携手各专家学者&#xff0c;共同挖掘智能与虚拟的无限可能…

【C++初阶】 vector 在OJ中的使用

前言&#xff1a; &#x1f3af;个人博客&#xff1a;Dream_Chaser &#x1f388;博客专栏&#xff1a;C &#x1f4da;本篇内容&#xff1a;只出现一次的数字 和 杨辉三角 OJ 目录 一、只出现一次的数字 题目描述&#xff1a; 二、杨辉三角OJ 题目描述&#xff1a; 一、只…

AI设计优化电机、电路与芯片?

一、AI进行电机本体设计 使用AI进行电机本体设计是一种前沿且具有潜力的方法&#xff0c;通过深度学习、强化学习、遗传算法等AI技术&#xff0c;可以实现电机设计的自动化和优化。具体应用可以包括以下几个方面&#xff1a; 此图片来源于网络 1. **参数优化**&#xff1a; …

docker + miniconda + python 环境安装与迁移(详细版)

本文主要列出从安装dockerpython环境到迁移环境的整体步骤。windows与linux之间进行测试。 简化版可以参考&#xff1a;docker miniconda python 环境安装与迁移&#xff08;简化版&#xff09;-CSDN博客 目录 一、docker 安装和测试 二、docker中拉取miniconda&#xff…

vscode 连接远程服务器 服务器无法上网 离线配置 .vscode-server

离线配置 vscode 连接远程服务器 .vscode-server 1. .vscode-server下载 使用vscode连接远程服务器时会自动下载配置.vscode-server文件夹&#xff0c;如果远程服务器无法联网&#xff0c;则需要手动下载 1&#xff09;网址&#xff1a;https://update.code.visualstudio.com…

ICP备案工信部短信核验怎么看是否成功?

备案短信核验怎么看是否成功&#xff1f;在工信部官网输入6位短信验证码、手机号和身份证号后&#xff0c;点击提交&#xff0c;会返回尊敬的ICP用户&#xff1a; 您的短信核验已全部完成,该请求将提交管局审核。如下图&#xff1a; 尊敬的ICP用户&#xff1a; 您的短信核验已全…

ArcGis研究区边界提取

ArcGis研究区边界提取 *0* 引言*1* 有的步骤0 引言 GRACE数据处理前要先确定研究范围,而大多情况下所选的研究区都是有特殊意义的,比如常年干旱、经济特区、降水丰富等,这些区域往往有精确的边界,那就要从大的区块中将研究范围抠出来,获取相应坐标,以量化区域重力变化。那…

蓝桥集训之斐波那契数列

蓝桥集训之斐波那契数列 核心思想&#xff1a;矩阵乘法 将原本O(n)的递推算法优化为O(log2n) 构造1x2矩阵f和2x2矩阵a 发现f(n1) f(n) * a 则f(n1) f(1) * an可以用快速幂优化 #include <iostream>#include <cstring>#include <algorithm>using na…

白嫖 kimi.ai 的 API 接口,给这个开源项目点赞!

Kimi 是当前国内相当火爆的 AI 产品&#xff0c;输出结果和使用体验都非常不错。 Kimi 开放了 API 接口&#xff0c;新用户注册后会免费赠送 15 元额度。 Kimi API 的网址&#xff1a; platform.moonshot.cn/console 这是光明正大的白嫖方式&#xff0c;一定不要错过哦。 如…

【机器学习300问】61、逻辑回归与线性回归的异同?

本文讲述两个经典机器学习逻辑回归&#xff08;Logistic Regression&#xff09;和线性回归&#xff08;Linear Regression&#xff09;算法的异同&#xff0c;有助于我们在面对实际问题时更好的进行模型选择。也能帮助我们加深对两者的理解&#xff0c;掌握这两类基础模型有助…

算法设计与分析实验报告c++实现(排序算法、三壶谜题、交替放置的碟子、带锁的门)

一、实验目的 1&#xff0e;加深学生对分治法算法设计方法的基本思想、基本步骤、基本方法的理解与掌握&#xff1b; 2&#xff0e;提高学生利用课堂所学知识解决实际问题的能力&#xff1b; 3&#xff0e;提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1、 编…

计算机网络学习

OSI 七层模型 物理层&#xff08;Physical Layer&#xff09; 功能&#xff1a;处理与电气或物理规范的接口有关的细节&#xff0c;如电缆类型、电信号传输和接收、网络设备的物理特性等。设备&#xff1a;包括网线、光纤、集线器等。 数据链路层&#xff08;Data Link Laye…

AcWing---公约数---最大公约数

4199. 公约数 - AcWing题库 思路&#xff1a; 最大整数x一定是最大公约数的因数&#xff0c;所以先用__gcd(a,b)求出a和b的最大公因数&#xff0c;再用O(log(n))的算法求出最大公因数的因数&#xff0c;放到vector中&#xff0c;并将vector排序。利用STL中的upper_bound(res.…

Star GAN论文解析

论文地址&#xff1a;https://arxiv.org/pdf/1912.01865v1.pdf https://openaccess.thecvf.com/content_cvpr_2018/papers/Choi_StarGAN_Unified_Generative_CVPR_2018_paper.pdf 源码&#xff1a;stargan项目实战及源码解读-CSDN博客 1. 概述 在传统方法中&#x…

游戏引擎之高级动画技术

一、动画混合 当我们拥有各类动画素材&#xff08;clips&#xff09;时&#xff0c;要将它们融合起来成为一套完整的动画。 最经典的例子就是从走的动画自然的过渡到跑的动画。 1.1 线性插值 不同于上节课的LERP&#xff08;同一个clip内不同pose之间&#xff09;&#xff…

JVM 内存溢出排查

说明&#xff1a;记录一次JVM内存溢出的排查过程&#xff1b; 场景 项目开发完成后&#xff0c;首次提交到测试环境。测试、产品同事反馈页面先是操作响应慢&#xff0c;抛出超时异常&#xff0c;最后直接无法使用。查看日志后得知是内存溢出。 重启服务后&#xff0c;我对前…

SV学习笔记(五)

线程的使用 程序和模块 module&#xff08;模块&#xff09;作为SV从verilog继承过来的概念&#xff0c;自然地保持了它的特点&#xff0c;除了作为RTL模型的外壳包装和实现硬件行为&#xff0c;在更高层的集成层面&#xff0c;模块之间也需要通信和同步。 对于硬件的过程块&…

记录一下前端定时器清除失效的问题

目录 一、问题引入 二、错误代码&#xff1a; 三、错误原因 四、修正的代码 附 vue提供的线上运行代码网址以便证实可用性 一、问题引入 按理说&#xff0c;打开定时器 xxx setInterval(()>{ },100)&#xff0c;之后只要 clearInterval(xxx) 就可以顺利关闭定时器…

【漏洞复现】用友NC Cloud前台命令执行漏洞

0x01 阅读须知 “如棠安全的技术文章仅供参考&#xff0c;此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供…