算法练习-左叶子之和(思路+流程图+代码)

难度参考

        难度:中等

        分类:二叉树

        难度与分类由我所参与的培训课程提供,但需要注意的是,难度与分类仅供参考。且所在课程未提供测试平台,故实现代码主要为自行测试的那种,以下内容均为个人笔记,旨在督促自己认真学习。

题目

        计算给定二叉树的所有左叶子之和。
        示例1:
        输入:root=[3,9,20,null,nu,15,7]
        输出:24
        解释:在这个二叉树中,有两个左叶子,分别是9和15,所以返回24

        示例2:
        输入:root=[1]
        输出:0

思路

        计算给定二叉树的所有左叶子之和的问题的思路主要是通过递归遍历一颗二叉树的所有节点,并且识别哪些节点是左叶子节点(即,一个节点没有子节点并且是其父节点的左子节点)。以下是解决该问题的具体思路:

  1. 确认基本情况:如果当前节点为空,那么它不会对左叶子之和作任何贡献,返回0。

  2. 检查当前节点是否为左叶子节点,即它是不是其父节点的左子节点且没有子节点。如果是,将它的值加到左叶子之和上。

  3. 对于每个非空节点,递归检查它的左子节点和右子节点:

    • 对左子节点调用递归函数,同时将当前节点作为父节点传递。
    • 对右子节点也调用递归函数,并同样将当前节点作为父节点传递。
  4. 从左右子树接收到的左叶子之和需要合计到当前总和中。

  5. 递归过程持续进行,直到所有节点被访问。

  6. 一旦所有节点被递归遍历完毕,可以得到所有左叶子节点之和。

  7. 最后,返回这个总和值给调用的地方,通常是在主函数中对这个递归函数的初始调用。

示例

        假设有一棵这样的二叉树:

        3/ \9  20/  \15   7

        在这颗树中,节点 9 和节点 15 是左叶子节点。

        首先注意,左节点是不是根节点,并且是其父节点的左子节点,且没有左子树和右子树的节点。

  1. 程序从 main 函数调用 sumOfLeftLeaves 函数开始执行,并传入二叉树的根节点 root(节点值为3)。

  2. sumOfLeftLeaves 函数首先检查传入的节点不为空。这个检查用于结束递归调用。

  3. 因为我们从根节点(节点 3)开始,它没有父节点,所以不会被当作左叶子。

  4. 我们首先递归进入根节点的左子节点(节点 9)。在这一步中,传入的父节点是根节点(节点 3)。

  5. 在调用 sumOfLeftLeaves(root->left, root) 时,函数检测到节点 9 没有子节点,并且它是其父节点(节点 3)的左子节点,因此节点 9 被认为是一个左叶子,其值被加入到和中。

  6. 递归继续从节点 9 的左子节点和右子节点(两者均为空)调用 sumOfLeftLeaves,但是这些调用立即返回 0,不会对总和产生影响。

  7. 接下来,从根节点(节点 3)的递归调用进入其右子节点(节点 20),此时函数需要检查节点 20 的左右子节点。

  8. 当递归调用 sumOfLeftLeaves(root->right->left, root->right)(节点 15)时,它会发现节点 15 没有子节点,并且是其父节点(节点 20)的左子节点。于是节点 15 的值也被加入到和中。

  9. 当 sumOfLeftLeaves 递归调用节点 20 的右子节点(节点 7),这会导致最终返回 0,因为它不满足左叶子的条件。

  10. 随着递归调用的完成,每个节点对总和的贡献(如果它是左叶子节点)会被累加起来。

  11. 最终,所有的调用完成后,回到 main 函数中打印出了所有左叶子之和。

        所以,在上面的二叉树示例中,左叶子节点是节点 9 和节点 15,它们的值分别是 9 和 15,所以 sumOfLeftLeaves(root) 将会返回 9 + 15 = 24,这个值会在 main 函数中被打印出来。

梳理

        这样实现的原因在于算法正确地定义了何为左叶子节点,并且逐步遍历了二叉树的每个节点去判断是否符合左叶子节点的定义。算法的关键步骤在于:

  1. 左叶子的定义

    • 必须是一个叶子节点,意即没有子节点。
    • 必须是它父节点的左子节点。
  2. 递归的使用

    • 算法通过递归的方式遍历树中的所有节点。
    • 对于每个节点,递归函数会先判断该节点是否是左叶子节点。
    • 如果是,它会加上该节点的值到总和中。
    • 接着,算法会递归地调用当前节点的左右子节点,并传递当前节点作为新调用的父节点。
    • 递归的终止条件是当访问到的节点为 NULL,即没有子节点时。
  3. 累积求和

    • 在遍历树的同时,将碰到的所有符合条件的左叶子节点的值累加起来。
    • 每次对节点调用递归函数时,将返回的和(对左右子树递归调用的结果)累积到当前和中。

        递归其实不适合用流程图表示,但目前不会别的方法。

代码

#include <iostream>
using namespace std;// 定义二叉树节点的结构体
struct TreeNode {int val;                // 节点内的值TreeNode *left;         // 指向左子树的指针TreeNode *right;        // 指向右子树的指针TreeNode(int x) : val(x), left(NULL), right(NULL) {} // 初始化结构体的构造函数
};// 辅助函数,判断一个节点是否是左叶子节点
bool isLeftLeave(TreeNode* node, TreeNode* parent) {// 如果节点不是根节点,并且是其父节点的左子节点,且没有左子树和右子树,则为左叶子节点if (parent && parent->left == node && node->left == NULL && node->right == NULL) {return true;}return false;
}// 计算所有左叶子之和的递归函数
int sumOfLeftLeaves(TreeNode* root, TreeNode* parent = NULL) {if (!root) return 0; // 如果节点为空,则返回0int sum = 0; // 初始化左叶子之和为0if (isLeftLeave(root, parent)) { // 如果当前节点是左叶子节点,则将其值加到sum上sum += root->val;}sum += sumOfLeftLeaves(root->left, root); // 递归计算左子树的左叶子之和sum += sumOfLeftLeaves(root->right, root); // 递归计算右子树的左叶子之和return sum; // 返回计算的左叶子之和
}// 主函数
int main() {// 根据提供的例子手动创建二叉树,以下代码根据示例1构建二叉树TreeNode* root = new TreeNode(3);root->left = new TreeNode(9); // 左叶子节点root->right = new TreeNode(20);root->right->left = new TreeNode(15); // 左叶子节点root->right->right = new TreeNode(7);// 计算左叶子之和并输出cout << "Sum of left leaves: " << sumOfLeftLeaves(root) << endl;// 清理申请的内存 (这部分代码省略,实际使用时需注意内存释放)return 0; // 程序结束
}

打卡

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

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

相关文章

高级编程 (1)

Linux软件编程: 1.Linux: 操作系统的内核 1.管理CPU 2.管理内存 3.管理硬件设备 4.管理文件系统 5.任务调度 2.Shell: 1.保护Linux内核(用户和Linux内核不直接操作,通过操作Shell,Shell和内核交互) 2.命令解释器 3.Shell命令: …

不是,哎呦~~,你怎么还是不会字母大小写的相互转化啊~

不是&#xff0c;哎呦~~&#xff0c;你怎么还是不会字母大小写的相互转化啊~~~ -------菜&#xff0c;就多练&#xff0c;以前是以前&#xff0c;现在是现在&#xff0c;以前不会不代表之后不会&#xff0c;赶紧看看怎么转化吧&#xff01;&#xff01;&#xff01; 接下来我会…

接口自动化测试详解

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 引言 与UI相比&#xff0c;接口一旦研发完成&#xff0c;通常变…

【TCP】四次挥手(终止连接)

前言 TCP&#xff08;传输控制协议&#xff09;是互联网协议&#xff08;IP&#xff09;中的一种重要传输层协议&#xff0c;用于在通信的计算机之间建立可靠的、有序的和错误校验的数据传输。在TCP连接中&#xff0c;数据传输是双向的&#xff0c;因此需要一种机制来开始和结…

前端面试拼图-数据结构与算法

摘要&#xff1a;总结一些前端算法题&#xff0c;持续更新&#xff01; 一、数据结构与算法 时间复杂度-程序执行时需要的计算量&#xff08;CPU&#xff09; 空间复杂度-程序执行时需要的内存空间 前端开发&#xff1a;重时间&#xff0c;轻空间 1.把一个数组旋转k步 arr…

第14章_视图

第14章_视图 1.常见的数据库对象 对象描述表(TABLE)表是存储数据的逻辑单元&#xff0c;以行和列的形式存在&#xff0c;列就是字段&#xff0c;行就是记录数据字典就是系统表&#xff0c;存放数据库相关信息的表。系统表的数据通常由数据库系统维护&#xff0c; 程序员通常不…

NUXTJS安装始终报错无法正常运行问题解决

近日在了解NuxtJS&#xff0c;按照官方给出方法进行安装后&#xff0c;不是报错&#xff0c;就是安装成功后运行不了。执行npm run dev后始终运行出错&#xff0c;判断肯定是对应版本问题&#xff0c;沿着这方向研究&#xff0c;最终运行成功了。 文档地址&#xff1a;安装 - …

一篇文章解决你的无线AP选型难题:从入门到精通

无线网络覆盖项目中&#xff0c;无线AP的合理选型和部署非常重要。今天给大家安排。 这篇文章&#xff0c;给你总结了6类典型的无线组网场所&#xff0c;针对每种场景的特点&#xff0c;给出相应的设备选型和部署的方案&#xff0c;同时整理了一些部署无线AP过程中容易忽略的细…

爬虫笔记(三):实战qq登录

咳咳&#xff0c;再这样下去会进橘子叭hhhhhh 以及&#xff0c;这个我觉得大概率是成功的&#xff0c;因为测试了太多次&#xff0c;登录并且验证之后&#xff0c;qq提醒我要我修改密码才可以登录捏QAQ 1. selenium 有关selenium具体是啥&#xff0c;这里就不再赘述了&#x…

奇瑞瑞虎8,是真不能随便碰

文 | AUTO芯球 作者 | 李虎 我是实在看不下去了啊 这奔驰车主砸车 现在开始反转了啊 但卡住我喉咙的是定损5200的奇瑞引擎盖啊 我是真买不起&#xff0c;也不敢买啊 我怕A柱断了&#xff0c;要修20万啊 但我一算&#xff0c;这也不对啊 顶配的报价也只有16.18万啊 如果…

提升 Web 请求效率:Axios request 封装技巧

在开发中&#xff0c;为了提高效率&#xff0c;通常对 Axios 进行封装&#xff0c;简化了请求的发送和对响应的处理。同时&#xff0c;统一错误处理机制有助于维护代码的清晰和一致性。本文介绍了一些高效封装 Axios 请求的方法。 封装理念 通过创建一个请求函数&#xff0c;我…

docker镜像结构

# 基础镜像 FROM openjdk:11.0-jre-buster # 设定时区 ENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # 拷贝jar包 COPY docker-demo.jar /app.jar # 入口 ENTRYPOINT ["java", "-jar"…