DAY15|二叉树Part03|LeetCode: 222.完全二叉树的节点个数、110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和

目录

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

基本思路

普通二叉树

完全二叉树

C++代码

LeetCode: 110.平衡二叉树

基本思路

C++代码

LeetCode: 257. 二叉树的所有路径

基本思路

C++代码

LeetCode: 404.左叶子之和

基本思路

C++代码


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

力扣代码链接

文字讲解:LeetCode: 222.完全二叉树的节点个数

视频讲解:要理解普通二叉树和完全二叉树的区别!

基本思路

        对于本题来讲,可以将其视为普通二叉树求解也可以单独考虑完全二叉树的情况来求解

普通二叉树

作为普通二叉树,可以使用递归法进行求解,也可以考虑通过层序遍历,一层层统计出二叉树节点数量,下面以递归法为例:

  • 确定递归函数的参数和返回值

        传入的是根节点,返回该节点为二叉树的根节点的节点数量,为int类型。

int getNodesNum(TreeNode* cur) {
  • 确定终止条件

        当节点为空时,说明包含的节点数为零,返回0。

if (cur == NULL) return 0;
  • 确定单层递归逻辑

        先求它的左子树的节点数量,再求右子树的节点数量,最后取总和再加一 (加1是因为算上当前中间节点)就是目前节点为根节点的节点数量。

int leftNum = getNodesNum(cur->left);      // 左
int rightNum = getNodesNum(cur->right);    // 右
int treeNum = leftNum + rightNum + 1;      // 中
return treeNum;

完全二叉树

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

        完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。

        对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。

        对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。

  • 确定递归函数的参数和返回值

传入的是根节点,返回该节点为二叉树的根节点的节点数量,为int类型。

int countNodes(TreeNode* root) {
  • 确定终止条件

当节点为空时,说明节点数量为0,返回0,然后需要对当前子树是否为满二叉树进行判断,因为满二叉树一定是完全二叉树,而满二叉树的节点数量很好计算,为2^n-1,其中n为二叉树的深度。

此时可以记录并根据左深度和右深度来判断子树是否为满二叉树,如果相等,则说明是当前子树为满二叉树,直接返回二叉树的节点数量2^左深度-1。

if (root == nullptr) return 0; 
// 开始根据左深度和右深度是否相同来判断该子树是不是满二叉树
TreeNode* left = root->left;
TreeNode* right = root->right;
int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
while (left) {  // 求左子树深度
    left = left->left;
    leftDepth++;
}
while (right) { // 求右子树深度
    right = right->right;
    rightDepth++;
}
if (leftDepth == rightDepth) {
    return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,返回满足满二叉树的子树节点数量
}
  • 确定单层递归逻辑

        如果左深度和右深度不相等,则继续递归,记录左子树的节点数量和右子树的节点数量,最后加1(根节点)即为完全二叉树的节点数量。

int leftTreeNum = countNodes(root->left);       // 左
int rightTreeNum = countNodes(root->right);     // 右
int result = leftTreeNum + rightTreeNum + 1;    // 中
return result;

C++代码

// 普通二叉树
class Solution {
private:
    int getNodesNum(TreeNode* cur) {
        if (cur == NULL) return 0;
        int leftNum = getNodesNum(cur->left);      // 左
        int rightNum = getNodesNum(cur->right);    // 右
        int treeNum = leftNum + rightNum + 1;      // 中
        return treeNum;
    }
public:
    int countNodes(TreeNode* root) {
        return getNodesNum(root);
    }
};


//完全二叉树
class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr) return 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便
        while (left) {  // 求左子树深度
            left = left->left;
            leftDepth++;
        }
        while (right) { // 求右子树深度
            right = right->right;
            rightDepth++;
        }
        if (leftDepth == rightDepth) {
            return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
        }
        int leftTreeNum = countNodes(root->left);       // 左
        int rightTreeNum = countNodes(root->right);     // 右
        int result = leftTreeNum + rightTreeNum + 1;    // 中
        return result;
    }
};

LeetCode: 110.平衡二叉树

力扣代码链接

文字讲解:LeetCode: 110.平衡二叉树

视频讲解:后序遍历求高度,高度判断是否平衡

基本思路

        一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。对于求高度,我们应该选择后序遍历,因为求深度可以从上到下去查 所以需要前序遍历(中左右),而高度只能从下到上去查,所以只能后序遍历(左右中)。

        使用递归法步骤如下:

  • 确定递归函数的参数和返回值

        参数为当前传入的节点,返回值为当前节点的高度,为int类型。其中如果子树不是平衡二叉树,我们就向中间节点传入-1,并最终传到根节点。

// -1 表示已经不是平衡二叉树了,否则返回值是以该节点为根节点树的高度
int getHeight(TreeNode* node)
  • 确定终止条件

        递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0

if (node == NULL) {
    return 0;
}
  • 确定单层递归逻辑

        分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则返回-1,表示已经不是二叉平衡树了。

int leftHeight = getHeight(node->left); // 左
if (leftHeight == -1) return -1;
int rightHeight = getHeight(node->right); // 右
if (rightHeight == -1) return -1;

int result;
if (abs(leftHeight - rightHeight) > 1) {  // 中
    result = -1;
} else {
    result = 1 + max(leftHeight, rightHeight); // 以当前节点为根节点的树的最大高度
}

return result;

C++代码

class Solution {
public:
    // 返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树了则返回-1
    int getHeight(TreeNode* node) {
        if (node == NULL) {
            return 0;
        }
        int leftHeight = getHeight(node->left);
        if (leftHeight == -1) return -1;
        int rightHeight = getHeight(node->right);
        if (rightHeight == -1) return -1;
        int result;
        if (abs(leftHeight - rightHeight) > 1) {  // 中
            result = -1;
        } else {
            result = 1 + max(leftHeight, rightHeight); // 以当前节点为根节点的树的最大高度
        }

        return result;
    }
    bool isBalanced(TreeNode* root) {
        return getHeight(root) == -1 ? false : true;
    }
};

LeetCode: 257. 二叉树的所有路径

力扣代码链接

文字讲解:LeetCode: 257. 二叉树的所有路径

视频讲解:递归中带着回溯,你感受到了没?

基本思路

        这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。

        在这道题目中将第一次涉及到回溯,因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。

依旧使用递归的方法进行求解:

  • 确定递归函数的参数和返回值。

        需要传入的参数为根节点,并且记录所搜索的路径,以及将搜索到的路径结果保存在变量result中。

void traversal(TreeNode* cur, vector<int>& path, vector<string>& result)
  • 确定终止条件

        和前面的题目不同,不再是节点为空时停止,因为当搜索到叶子节点时,就需要将路径记录在result中,即cur指针指向的节点不为空,但是左右孩子为空。而根据题目要求节点之间需要用->进行连接,因此需要对路径中的节点进行遍历,并加入->。

if (cur->left == NULL && cur->right == NULL) { // 遇到叶子节点
    string sPath;
    for (int i = 0; i < path.size() - 1; i++) { // 将path里记录的路径转为string格式
        sPath += to_string(path[i]);
        sPath += "->";
    }
    sPath += to_string(path[path.size() - 1]); // 记录最后一个节点(叶子节点)
    result.push_back(sPath); // 收集一个路径
    return;
}
  • 确定单层递归逻辑

        因为是前序遍历,需要先处理中间节点,中间节点就是我们要记录路径上的节点,先放进path中。如果和之前的题目中的顺序一样,当节点的左右孩子都为空时,就直接返回路径,此时就不会包含叶子结点。

path.push_back(cur->val);

        而我们在进行递归之后,需要进行回溯。

if (cur->left) {
    traversal(cur->left, path, result);
    path.pop_back(); // 回溯
}
if (cur->right) {
    traversal(cur->right, path, result);
    path.pop_back(); // 回溯
}

C++代码

class Solution {
private:
    void traversal(TreeNode* cur, vector<int>& path, vector<string>& result) {
        path.push_back(cur->val); // 中,中为什么写在这里,因为最后一个节点也要加入到path中 
        // 这才到了叶子节点
        if (cur->left == NULL && cur->right == NULL) {
            string sPath;
            for (int i = 0; i < path.size() - 1; i++) {
                sPath += to_string(path[i]);
                sPath += "->";
            }
            sPath += to_string(path[path.size() - 1]);
            result.push_back(sPath);
            return;
        }
        if (cur->left) { // 左 
            traversal(cur->left, path, result);
            path.pop_back(); // 回溯
        }
        if (cur->right) { // 右
            traversal(cur->right, path, result);
            path.pop_back(); // 回溯
        }
    }

public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> result;
        vector<int> path;
        if (root == NULL) return result;
        traversal(root, path, result);
        return result;
    }
};

LeetCode: 404.左叶子之和

力扣代码链接

文字讲解:LeetCode: 404.左叶子之和

视频讲解:二叉树的题目中,总有一些规则让你找不到北

基本思路

        最重要的是要确定二叉树中哪些节点是左叶子,如果一个节点的左右孩子为空,那么我们就可以认为这个节点是叶子节点,那么在这个基础上进行延伸,如果一个节点有左孩子,并且左孩子的左右孩子都为空,那么这个节点的左孩子不就是所谓的左叶子节点了吗?

使用递归法进行求解:

  • 确定递归函数的参数和返回值。

首选我们需要传入根节点,返回的是左叶子节点的和,为int类型。

int sumOfLeftLeaves(TreeNode* root) 
  • 确定终止条件

        对二叉树的所有节点进行遍历,如果节点为空时,就返回零,说明此时不存在左叶子节点。但是我们如果遍历的节点为叶子节点时(包括左右叶子节点)我们应该怎么办呢?这个时候我们同样返回0(因为此时还不能确定是左叶子节点还是右叶子节点,我们必须看叶子节点是否为其父节点的左孩子)。

if (root == NULL) return 0;
if (root->left == NULL && root->right== NULL) return 0; //其实这个也可以不写,如果不写不影响结果,但就会让递归多进行了一层。
  • 确定单层递归逻辑

        当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。

int leftValue = sumOfLeftLeaves(root->left);    // 左
if (root->left && !root->left->left && !root->left->right) {
    leftValue = root->left->val;
}
int rightValue = sumOfLeftLeaves(root->right);  // 右

int sum = leftValue + rightValue;               // 中
return sum;

C++代码

class Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        if (root == NULL) return 0;
        if (root->left == NULL && root->right== NULL) return 0;

        int leftValue = sumOfLeftLeaves(root->left);    // 左
        if (root->left && !root->left->left && !root->left->right) { // 左子树就是一个左叶子的情况
            leftValue = root->left->val;
        }
        int rightValue = sumOfLeftLeaves(root->right);  // 右

        int sum = leftValue + rightValue;               // 中
        return sum;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何创建项目管理的WBS?

在项目管理中&#xff0c;工作分解结构&#xff08;WBS&#xff09;是确保项目按计划推进的重要工具。创建WBS的过程不仅关乎任务的分配&#xff0c;还影响项目的整体管理效率。以下是蓝燕云项目管理团队总结的一些有效的创建WBS的方法和指导方针&#xff0c;帮助项目管理团队更…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-22目录1. PoisonedRAG: Knowledge corruption attacks to retrieval-augmented generation of large language models摘要创新点…

Flutter学习笔记(一)-----环境配置

一、android 环境 android这边可以参照godot的配置 1.装java Java Downloads | Oracle x64 Compressed Archive &#xff1a;下载后直接解压到某个位置&#xff0c;不用安装 x64 installer: 下载后双击安装 注意&#xff1a;不要去百度直接搜Java安装&#xff0c;这样你最多安…

华为配置 之 IPv6路由配置

目录 简介&#xff1a; 知识点&#xff1a; IPv6静态路由配置&#xff1a; IPv6默认路由配置&#xff1a; 总结&#xff1a; 简介&#xff1a; IPv6&#xff08;Internet Protocol Version 6&#xff09;是网络层协议的第二代标准协议&#xff0c;也被称为IPng&#xff08;…

NIM 平台生成式 AI-demo

需要python环境 官网注册&#xff1a;&#xff08;后续调用模型需要秘钥key&#xff09;Try NVIDIA NIM APIs 可以看到有多种模型&#xff1a; 官方案例 1.安装相关依赖&#xff1a; pip install langchain_nvidia_ai_endpoints langchain-community langchain-text-splitt…

《Python网络安全项目实战》

《Python网络安全项目实战》 项目1 Python 环境安装任务1.1 Windows上安装Python任务1.2 Ubuntu环境下安装Python 项目2 Python基础练习任务2.1 使用数据类型任务2.2 使用组合数据类型任务2.3 使用控制结构任务2.4 使用函数任务2.5 使用模块 项目3 处理文件中的数据任务3.1 读文…

​双十一买什么比较划算?2024年双十一必买好物推荐

双十一期间哪些商品最值得购买&#xff1f;一年一度的双十一购物狂欢节又如约而至&#xff0c;各大电商平台纷纷推出了各种优惠活动和促销策略&#xff0c;让人眼花缭乱。在这个全民购物的盛宴中&#xff0c;如何才能买到真正划算的好物&#xff0c;成为了许多消费者关注的焦点…

AI视频王者归来-[ComfyUI]PyramidFlow:快手开源视频模型,与Mochi比拼谁更强?8G可运行10秒768P与24帧视频生成

在人工智能视频生成的领域&#xff0c;ComfyUI的PyramidFlow和Mochi两款模型一直是业界关注的焦点。而最近&#xff0c;快手开源了PyramidFlow模型&#xff0c;引发了与Mochi模型的新一轮比拼。那么&#xff0c;究竟哪一款模型更胜一筹呢&#xff1f; PyramidFlow和Mochi的比拼…

Vivo开奖了,劝退价。。

vivo 也开奖了&#xff0c;不过有小伙伴反馈是个劝退价&#xff0c;甚至不如隔壁的 oppo&#xff0c;要说这两家也是渊源颇深&#xff0c;一家是绿厂&#xff0c;一家是蓝厂&#xff0c;高管也都是早期步步高出来的。 给大家盘一下开奖的信息&#xff0c;方便大家横向做个对比&…

【C++】哈希表模拟:闭散列技术与哈希冲突处理

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriori…

SketchUp 云渲染—助力您的渲染

目前市面上的渲染平台有很多&#xff0c;但是能支持SketchUp云渲染的特别少&#xff0c;大部分云渲染是还是不支持的&#xff0c;今天就给大家介绍国内支持Sketchup渲染的云渲染——【渲染101】云渲染的使用方法。 1、官网下载最新的客户端并且安装。 2、登录客户端配置好对应…

栈和队列(2)——队列

队列的基本概念 1. 队列定义&#xff1a;只允许在一端进行插入&#xff0c;在另一端进行删除的线性表。 2. 队列特点&#xff1a;先进先出&#xff08;FIFO&#xff09;。 3. 队列基本操作&#xff1a;初始化队列、销毁队列、入队、出队、读队头元素、判队列空等。 InitQueue…

凭什么你说不是就不是-zzj杯·UMLChina建模答题赛第6赛季第2轮

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 参考潘加宇在《软件方法》和UMLChina公众号文章中发表的内容作答。在本文下留言回答。 只要最先答对前3题&#xff0c;即可获得本轮优胜。 如果有第4题&#xff0c;第4题为附加题&am…

【hacker送书第14期】AI训练师算法与模型训练从入门到精通

全面精通人工智能训练&#xff0c;成为行业领先、更懂AI的人&#xff01; 前言内容简介总结参与方式 前言 在人工智能&#xff08;AI&#xff09;技术日益成熟的今天&#xff0c;AI训练师成为了一个新兴且重要的职业。他们不仅需要掌握AI的核心技术&#xff0c;还要能够将这些…

一文详细讲解进销存系统(附架构图、流程、功能介绍)

企业经营的七大要素是“人、财、物、产、供、销、存”&#xff0c;进销存管理就占到了其中的多项。然而&#xff0c;许多企业在进销存管理方面面临着诸多痛点问题&#xff0c;例如库存管理混乱、采购销售流程不清晰、数据不准确等。这些问题不仅影响企业的运营效率&#xff0c;…

如何在Python爬虫等程序中设置和调用http代理

在Python爬虫中为了更好地绕过反爬机制&#xff0c;获取网页信息&#xff0c;有时可能需要在Python中应用代理服务&#xff0c;这样做的目的就是防止自己的ip被服务器封禁&#xff0c;造成程序运行时中断连接&#xff0c;那么如何在python中设置代理呢&#xff1f; 我们通过几个…

2024年【浙江省安全员-C证】试题及解析及浙江省安全员-C证复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【浙江省安全员-C证】试题及解析及浙江省安全员-C证复审考试&#xff0c;包含浙江省安全员-C证试题及解析答案和解析及浙江省安全员-C证复审考试练习。安全生产模拟考试一点通结合国家浙江省安全员-C证考试最新…

8、Node.js Express框架

五、Express框架 5.1概念 Express框架是一个基于Node.js平台的极简、灵活的WEB开发框架:www.express.com.cn 简单来说,Express是一个封装好的工具包,封装了很多功能,便于我们开发WEB应用 5.2安装 npm i express5.3 Express初体验 //01-express初体验.js //1.导入exrp…

Python(包和模块)

包 定义 包是将模块以文件夹的组织形式进行分组管理的方法&#xff0c;以便更好地组织和管理相关模块。 包是一个包含一个特殊的__init__.py文件的目录&#xff0c;这个文件可以为空&#xff0c;但必须存在&#xff0c;以标识目录为Python包。 包可以包含子包&#xff08;子…

万方数据库功能亮点介绍及个人下载万方论文的方法

一、万方数据库介绍 万方数据知识服务平台是北京万方数据股份有限公司主要产品之一。该平台整合数亿条全球优质学术资源&#xff0c;集成期刊、学位、会议、标准、专利等十余种资源类型、品质知识资源、先进的发现技术、人性化设计于一身&#xff0c;是国内一流的品质知识资源…