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

news2024/9/27 7:17:17

难度参考

        难度:中等

        分类:二叉树

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

题目

        计算给定二叉树的所有左叶子之和。
        示例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; // 如果节点为空,则返回0

    int sum = 0; // 初始化左叶子之和为0
    if (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.coloradmin.cn/o/1429777.html

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

相关文章

rust gui开发框架选择

作为一个系统编程强大语言&#xff0c;怎么能少得了图形界面的开发 实际上写这篇前我也不知道&#xff0c;于是我问了ai大模型&#xff0c;文心3.5和chatgpt4.0 答案实际上不能满意&#xff0c;最后我做了下筛选 参考博文&#xff1a; rust开发环境配置&#xff1a;链接 一、…

Loadbalancer如何优雅分担服务负荷

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Loadbalancer如何优雅分担服务负荷 前言Loadbalancer基础&#xff1a;数字世界的分配大师1. 分发请求&#xff1a;2. 健康检查&#xff1a;3. 会话保持&#xff1a;4. 可伸缩性&#xff1a;5. 负载均衡…

数据结构—基础知识:哈夫曼编码

文章目录 数据结构—基础知识&#xff1a;哈夫曼编码哈夫曼编码的主要思想有关编码的概念哈夫曼编码满足两个性质&#xff1a; 数据结构—基础知识&#xff1a;哈夫曼编码 哈夫曼编码的主要思想 在进行数据压缩时&#xff0c;为了使压缩后的数据文件尽可能短&#xff0c;可采…

二手电脑配置给你不一样的成就感

回顾从小到大使用电脑、组装电脑到开发软硬件的经历&#xff0c;总是对二手电脑有着不一样的情感&#xff0c;近五年买过八台新电脑&#xff0c;一台是图像处理培训买的笔记本&#xff0c;一台是小孩上课的台式机&#xff0c;一台是老人的集成办卡电脑&#xff0c;还有一些工作…

Vue3_基础使用_2

这节主要介绍&#xff1a;标签和组件的ref属性&#xff0c;父子组件间的传递值&#xff0c;ts的接口定义&#xff0c;vue3的生命周期 1.标签的ref属性。 1.1ref属性就是给标签打标识用的&#xff0c;相当于html的id&#xff0c;但是在vue3中用id可能会乱&#xff0c;下面是ref…

跟着cherno手搓游戏引擎【18】抽象Shader、项目小修改

抽象&#xff1a; Shader.h: #pragma once #include <string>namespace YOTO {class Shader {public:virtual~Shader()default;virtual void Bind()const0;virtual void UnBind()const0;static Shader* Create(const std::string& vertexSrc, const std::string&am…

软考高项-机考相关介绍论文写作基础介绍

机考相关 初、中级(信息处理技术员除外)资格:基础知识和应用技术2个科目连考,基础知识科目最短作答时长90分钟,最长作答时长120分钟,2个科目作答总时长240分钟,考试结束前60分钟可交卷离场 历年论文考题

java数据结构与算法刷题-----LeetCode15. 三数之和

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 和LeetCode1.两数之和一样&#xff0c;但是这道题边界条件更多。…

Flutter 各种Demo效果合集

Flutter 各种Demo实现效果&#xff1a; github&#xff1a;GitHub - PangHaHa12138/FlutterDemo: Flutter 各种Demo效果合集 1&#xff1a;2种 仿朋友圈 效果,顶部拉伸 和 不拉伸 2&#xff1a;仿抖音上下滑动视频播放 3&#xff1a;视频直播&#xff08;使用的电视台的m3u…

云计算基础(云计算概述)

目录 一、云计算概述 1.1 云计算的概念 1.1.1 云计算解决的问题 1.1.2 云计算的概念 1.1.3 云计算的组成 1.2 云计算主要特征 1.2.1 按需自助服务 1.2.2 泛在接入 1.2.3 资源池化 1.2.4 快速伸缩性 1.2.5 服务可度量 1.3 云计算服务模式 1.3.1 软件即服务(Softwar…

C#验证字符串是否包含汉字:用正则表达式 vs 用ASCII码 vs 用汉字的 Unicode 编码

目录 一、使用的方法 1.使用正则表达式验证字符串 2.使用正则表达式验证字符 3.用ASCII码判断 4.用汉字的 Unicode 编码范围判断 二、实例 1.源码 2.生成效果 验证一个字符串是否是纯汉字或者包含有汉字的前提&#xff0c;是VS编辑器的默认编码格式设置为&#xff1a;选…

Vite与Webpack打包内存溢出问题优雅处理方式

Vite与Webpack打包内存溢出问题处理 文章目录 Vite与Webpack打包内存溢出问题处理1. Vite1. 打包错误提示2. 命令行方式解决3. 配置环境变量方式解决1. 设置变量2. 配置系统的环境变量 2. Webpack1. 打包错误提示2. 命令行方式解决3. 配置环境变量方式解决1. 设置变量2. 配置系…

Llama2大模型开源,大模型的Android时代来了?

就昨天凌晨,微软和Meta宣布Llama2大模型开源且进一步放开商用,一下朋友圈刷屏。要知道,开源界最强大的模型就是过去Meta开源的Llama,而现在Llama2更强大,又开放商用,更有微软大模型霸主企业撑腰(微软既投资大模型界的IOS——ChatGPT,又联合发布大模型的Android——Llam…

旧衣物回收小程序开发,互联网模式下的营收有多大?

在当下快节奏的生活中&#xff0c;人们不仅生活水平在提高&#xff0c;消费水平也在逐渐提高&#xff0c;从而导致了闲置衣物的增加。为了减少浪费&#xff0c;旧衣服回收行业受到了大众的广泛关注&#xff0c;成为循环利用的一大方式。 当然&#xff0c;在当下网络时代&#…

Docker 阿里云镜像仓库CR使用实践

一、使用容器镜像&#xff0c;查看镜像&#xff0c;创建&#xff0c;推送&#xff0c;拉取阿里云镜像 CR镜像管理&#xff08;阿里云容器镜像服务&#xff08;Container Registry&#xff09;&#xff09; 登录实例 未创建的镜像名称也可以push、docker的私有仓库需要提起创建…

C语言——深入理解指针(1)

目录 1.内存和地址 a 内存的理解 b 如何理解编址 2.指针变量和地址 a 取地址操作符 b 指针变量 c 解引用操作符 d 指针变量的大小 1.内存和地址 a 内存的理解 假想这样一个场景&#xff0c;你的朋友找你玩&#xff0c;到了你家小区&#xff0c;如何让她迅速的找到…

时间复杂度为 O(n) 的排序算法

大家好&#xff0c;我是 方圆。本文介绍线性排序&#xff0c;即时间复杂度为 O(n) 的排序算法&#xff0c;包括桶排序&#xff0c;计数排序和基数排序&#xff0c;它们都不是基于比较的排序算法&#xff0c;大家重点关注一下这些算法的适用场景。 桶排序 桶排序是分治策略的一…

Sentinel应用笔记

概念 当A、B、G、H掉线&#xff0c;其他服务就没法通信了 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点&#xff0c;从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。 特性…

如何在PS5上使用金手指修改游戏

环境&#xff1a;windows PS5 问题&#xff1a;PS5 没有GodHen&#xff0c;无法使用json金手指&#xff0c;PKG金手指比较少 解决办法&#xff1a;使用MultiTrainerv从网络注入PS5&#xff0c;修改进程内存 背景&#xff1a;为了护肝&#xff0c;拒绝刷刷刷 解决过程&#xff…

切换登录时,清空input输入框

在uniapp登录页面时&#xff0c;会出现几种登录方式&#xff0c;当切换登录方式时&#xff0c;会出现input复用问题。像下面图中所示。 出现复用的原因是&#xff1a;Vue在进行Dom渲染时&#xff0c;出于性能考虑&#xff0c;会复用已经存在的元素&#xff0c;而不是重新创建新…