【LeetCode】222. 完全二叉树的节点个数(简单)——代码随想录算法训练营Day16

news2024/11/15 15:31:20

题目链接: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) 的简单解决方案。你可以设计一个更快的算法吗?

文章讲解:代码随想录

视频讲解:要理解普通二叉树和完全二叉树的区别! | LeetCode:222.完全二叉树节点的数量_哔哩哔哩_bilibili

题解1:递归法——针对任意二叉树

思路:使用后续遍历,递归的求出左子树和右子树节点数量,再加1即为整个二叉树的节点数量。

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var countNodes = function(root) {
    if (!root) {
        return 0;
    }
    return countNodes(root.left) + countNodes(root.right) + 1;
};

分析:时间复杂度为 O(n),空间复杂度为 O(logn)。

题解2:二叉树遍历——针对任意二叉树

思路:任意一种二叉树的遍历方式,边遍历边计数。这里使用前序遍历。

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var countNodes = function(root) {
    let count = 0;
    const preorder = function (node) {
        if (node) {
            count++;
            preorder(node.left);
            preorder(node.right);
        }
    };
    preorder(root);
    return count;
};

分析:时间复杂度为 O(n),空间复杂度为 O(logn)。

题解3:——针对完全二叉树

思路:题目中强调了这颗树是一个完全二叉树。根据完全二叉树的特性,对二叉树进行层序遍历,遇到第1个叶子节点或第1个只有左孩子的节点时,即可得出答案。

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var countNodes = function(root) {
    let count = 0;
    const queue = [];
    if (root) {
        queue.push(root);
    }
    while (queue.length > 0) {
        let size = queue.length;
        while (size--) {
            const node = queue.shift();
            count++;
            // 如果此节点为第1个叶子节点,二叉树的节点数则为到此节点的数量乘2减1
            if (!node.left) {
                return count * 2 - 1;
            }
            // 如果此节点为第1个没有右孩子的节点,二叉树的节点数则为到此节点的数量乘2
            if (!node.right) {
                return count * 2;
            }
            queue.push(node.left);
            queue.push(node.right);
        }
    }
    return count;
};

分析:时间复杂度为 O(n),空间复杂度为 O(n)。

题解4:递归+计算——针对完全二叉树

思路:设一个满二叉树的最大深度为 n,则这个满二叉树的节点数为2^n - 1。对于一个完全二叉树,一定可以递归的找到为满二叉树的左子树和右子树,根据公式解出答案。

递归分析:

  • 确定递归函数的参数和返回值:参数为当前子树的根节点,返回值为这颗子树的节点数量。
  • 确定递归终止条件:当前节点为空节点时,返回0;当前子树为满二叉树时,返回根据公式求出的结果。
  • 确定单层递归逻辑:返回左子树的节点树加上右子树的节点树再加1,即为当前子树的节点数。
/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var countNodes = function(root) {
    if (!root) {
        return 0;
    }
    let leftNum = 0, rightNum = 0;
    let left = root.left, right = root.right;
    // 计算最左节点深度
    while (left) {
        leftNum++;
        left = left.left;
    }
    // 计算最右节点深度
    while (right) {
        rightNum++;
        right = right.right;
    }
    // 最左节点深度等于最右节点深度,说明为满二叉树,计算结果
    if (leftNum === rightNum) {
        return (1 << leftNum + 1) - 1;
    }
    // 不为满二叉树,递归的计算左子树和右子树的节点数之和再加1
    return countNodes(root.left) + countNodes(root.right) + 1;
};

分析:时间复杂度为 O(log²n),空间复杂度为 O(logn)。

收获

学习了满二叉树和完全二叉树的理论知识,了解了它们的特性,学会了如何用这些特性来解决问题。

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

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

相关文章

电工必备:故障电弧探测器安装方式

故障电弧探测器可以对故障电弧&#xff08;包括故障并联电弧、故障串联电弧&#xff09;进行有效的检测&#xff0c; 当检测到线路中存在引起火灾的故障电弧时&#xff0c;可以进行现场的声光报警&#xff0c;并将报警信息传输 给电气火灾监控设备。 故障电弧探测器适用于工…

Python连接MQTT服务器订阅和发布主题-Python物联网开发

一、前言 在物联网开发中&#xff0c;掌握MQTT可以说是一项必备的技能&#xff0c;要使用Python连接MQTT服务器、订阅和发布主题&#xff0c;我们需要导入paho-mqtt库。 二、实现代码 在之前的文章中&#xff0c;我们也介绍了JAVA是如何连接MQTT服务器实现发布和订阅主题的功能…

详细介绍node中动态数据内容的压缩应用

未使用 compression 压缩文件时 代码演示&#xff1a; const express require("express"); // 在node express框架当中&#xff0c;对node express框架进行一个引入const app express(); // 利用express()调用&#xff0c;对实例化对象进行获取app.get("/&q…

外汇天眼:美国证券交易委员会(SEC)采纳了一系列规定,以加强与特殊目的收购公司(SPACs)相关的投资者保护

美国证券交易委员会&#xff08;SEC&#xff09;今天通过了一系列新规和修订&#xff0c;以增强特殊目的收购公司&#xff08;SPACs&#xff09;的首次公开募股&#xff08;IPOs&#xff09;中的披露&#xff0c;并在SPACs与目标公司之间的后续业务合并交易&#xff08;de-SPAC…

FinBert模型:金融领域的预训练模型

文章目录 模型及预训练方式模型结构训练语料预训练方式 下游任务实验结果实验一&#xff1a;金融短讯类型分类实验任务数据集实验结果 实验二&#xff1a;金融短讯行业分类实验任务数据集实验结果 实验三&#xff1a;金融情绪分类实验任务数据集实验结果 实验四&#xff1a;金融…

蓝桥杯省赛无忧 课件42 插入排序

01 插入排序的思想 02 插入排序的实现 03 例题讲解 #include <iostream> #include <vector> using namespace std; void insertionSort(vector<int>& arr) {int n arr.size();for (int i 1; i < n; i) {// 选择arr[i]作为要插入的元素int key arr…

linux系统配置本地yum源

配置本地yum源原因&#xff1a;没有网络&#xff0c;无法使用yum更新下载软件&#xff0c;所以验旧配置一个本地yum源 第一&#xff1a;挂载镜像或者拷贝一份目录下有repodate文件的源 1&#xff09;虚拟机cd/dvd需要绑定iso镜像文件如上图 2&#xff09;备份/etc/yum.repo.d目…

【SVD生成视频+可本地部署】ComfyUI使用(二)——使用Stable Video Diffusion生成视频 (2023.11开源)

SVD官方主页 &#xff1a; Huggingface | | Stability.ai || 论文地址 huggingface在线运行demo : https://huggingface.co/spaces/multimodalart/stable-video-diffusion SVD开源代码&#xff1a;Github&#xff08;含其他项目&#xff09; || Huggingface 在Comfyui使用&…

【Midjourney】绘画风格关键词

1.松散素描(Loose Sketch) "Loose sketch"&#xff08;松散素描&#xff09;通常指的是一种艺术或设计中的手绘风格&#xff0c;其特点是线条和形状的表现相对宽松、自由&#xff0c;没有过多的细节和精确度。这样的素描通常用于表达创意、捕捉概念或者作为设计的初步…

清华大学学生一行赴麒麟信安调研交流

1月24日&#xff0c;清华大学信息科学技术学院电子工程系学子组成的社会实践支队一行到访麒麟信安&#xff0c;调研交流长沙市先进计算产业发展情况和未来规划。 在公司展厅&#xff0c;清华大学学子详细了解了麒麟信安的发展历程、国产操作系统产业现状&#xff0c;以及麒麟信…

第三季《乐队风暴》全国总决赛圆满落幕

2024年1月21日&#xff0c;由广东珠江、盛娱星汇海选联合主办的第三季《乐队风暴》全国海选歌手赛道全国总决赛在广州罗格镇MUSIC LIVE&#xff08;太古仓店&#xff09;正式打响&#xff0c;第三季《乐队风暴》全国海选开启以来共有超8000人报名渴望登上绚丽舞台&#xff0c;从…

1.25 day2 C++

自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show()

草原超声波气象站

TH-CQX9在广袤无垠的草原上&#xff0c;有一种神秘而重要的设施正在默默地守护着这片美丽的土地&#xff0c;它就是草原超声波气象站。这不仅是一个高科技的气象观测平台&#xff0c;更是草原生态保护的重要一环。那么&#xff0c;草原超声波气象站究竟是什么&#xff1f;它又是…

Java 字符串03 String构造方式代码实现和内存分析 (黑马)

第一种方式&#xff1a; 第二种方式&#xff1a; 有参的字符串&#xff1a; 传递字符串 传递字符数组 应用场景&#xff1a;将abc字符串改为Qbc&#xff0c;那么可以将其转换为数组&#xff0c;然后进行修改&#xff0c;最后传入即可获得Qbc&#xff1b; 字节数组&#xff1a;…

python自动化测试面试题

1、自动化代码中,用到了哪些设计模式? 单例设计模式工厂模式PO设计模式数据驱动模式面向接口编程设计模式 2、什么是断言( Assert) ? 断言Assert用于在代码中验证实际结果是不是符合预期结果&#xff0c;如果测试用例执行失败会抛出异常并提供断言日志 3、什么是web自动化…

服务器运维小技巧(二)——如何进行监控告警

服务器运维难度高的原因&#xff0c;很大程度是因为服务器一旦出现问题&#xff0c;生产环境的业务就会受到严重影响&#xff0c;极有可能带来难以承担的后果。因此这份工作要求工程师保持高要求的服务质量&#xff0c;能够快速响应问题&#xff0c;及时解决问题。 但是“及时…

uniapp Android 离线打包之未配置appkey或配置错误

1、去官网申请appKey: 申请Appkey 2、项目中使用appKey: <meta-dataandroid:name"dcloud_appkey"android:value"794534204bbae06989........" />3、参考 官方教程&#xff0c;修改配置&#xff1a; 配置教程 注意&#xff1a; 本地的appId 和 官…

简单快速取消AlertDialog的白色背景框,AlertDialog设置圆角背景

问题描述&#xff1a; 产品需求弹出的提示框是圆角&#xff0c;使用shape 设置圆角背景后&#xff0c;弹出的AlertDialog提示框四个角有白色的背景&#xff0c;据分析这个背景是 AlertDialog 父组件的背景色。 解决方法&#xff1a; 将Dialog的背景设置为透明色&#xff0c;代…

OpenKruise :Kubernetes背后的托底

一、 诞生背景 Kubernetes 自身提供的应用部署管理功能&#xff0c;无法满足大规模应用场景的需求&#xff0c;例如应用发布时的原地升级策略&#xff0c;流式扩容&#xff0c;缩容顺序控制等等。所以OpenKruise的出现弥补了 Kubernetes 在应用部署、升级、防护、运维等领域的不…

【电子通识】传统网络变压器原理与生产流程

网络变压器也称为网络隔离变压器。传统的网络变压器贴片器件大概长的都类似以下这样&#xff1a; 在网络接口上所起的作用主要有信号耦合、高压隔离、阻抗匹配、电磁干扰抑制作用。它主要用在网络交换机、路由器、网卡等产品。 做为数据传输时使用网络变压器可以达到以下效果&a…