左叶子节点之和

力扣题目链接(opens new window)

计算给定二叉树的所有左叶子之和。

示例:

思路

注意审题,这里是要求 左叶子节点 之和

不是二叉树中的左侧节点之和,因此使用层序遍历是不合适的

我们要明确的是,到底什么是左叶子节点

举个例子:

根据上图以及题目给的例子可知,我们无法直接判断当前节点是否为左叶子节点(因为无法将其与左侧节点区分)

所以需要通过当前节点的父节点来判断其左孩子是不是左叶子

即:如果某一节点的左子节点不为空,但该左子节点自身的左右节点为空,则找到一个左叶子节点

处理逻辑:

if(node->left != NULL  && node->left->left == NULL && node->right->right == NULL){
//左叶子节点处理逻辑
}

本题仍然有递归和迭代两种解法

递归法

分析

三部曲

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

输入是根节点(每次的输入节点即为本次递归的根节点),返回值是左叶子节点之和,即int

2、确定终止条件

终止条件有两个,因为这里输入递归函数的“根节点”其实就是当前节点

如果当前节点为空,那么终止

如果当前节点以及是做叶子节点,那么也应该终止

if(root == NULL) return 0;
if(root->left == NULL &&root->right == NULL) return 0;

3、确定单层处理逻辑(即当前递归层的处理逻辑)

使用后序遍历的方式通过递归不断遍历左右子节点,并寻找左右子节点下的左叶子节点

如果遇到的话,就获取该节点的val,然后在每层递归返回值的时候累加左右子节点下的左叶子节点的值之和

//定义变量,存放左子节点的左叶子节点的值之和
int leftSum = sumOfLeftLeaves(root->left);//左
//找到左叶子节点
if(root->left != NULL && root->left->left == NULL && root->left->right == NULL){
leftSum = root->left->val;
}
//以上两行代码对应过程是”使用父节点来判断其左孩子是不是左叶子节点“ int rightSum = sumOfLeftLeaves(root->right);//右 int sum = leftSum + rightSum;//中
return sum;

一定要明确左叶子节点的概念

虽然我们也遍历右节点,但是是为了寻找右节点下是否有左子节点,该子节点下又是否进一步存在左叶子节点

所以当遍历到某个右节点,那之后的递归操作一定会持续到触发leftSum为止(即在该右节点的子节点中找到叶子节点)

代码
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
//确定终止条件
if(root == NULL) return 0;
if(root->left == NULL && root->right == NULL) return 0; //确定单层处理逻辑
//后序遍历
//定义变量,存放左子节点的左叶子节点的值之和
int leftSum = sumOfLeftLeaves(root->left);//左
//找到左叶子节点
if(root->left != NULL && root->left->left == NULL && root->left->right == NULL){
leftSum = root->left->val;
}
//以上两行代码对应过程是”使用父节点来判断其左孩子是不是左叶子节点“
int rightSum = sumOfLeftLeaves(root->right);//右 int sum = leftSum + rightSum;//中
return sum; }
};
注意

TBD

迭代法

分析

使用前中后序遍历都可以,具体操作和使用栈进行迭代法遍历一致

代码
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
//创建一个栈
stack<TreeNode*> st;
//判断根节点
if (root != NULL) st.push(root);
//定义结果变量
int res = 0;
while(!st.empty()){
//取出栈顶节点
TreeNode* node = st.top();
//弹出
st.pop();
//判断左叶子节点
if(node->left != NULL && node->left->left == NULL && node->left->right == NULL){
res += node->left->val;
}
//遍历左右子节点,压栈
if (node->left) st.push(node->left);
if (node->right) st.push(node->right);
}
return res;
}
};
注意

使用栈进行迭代法的前后序遍历时,要与层序遍历区分清楚

在while中,迭代法前后序遍历不需要记录当前栈的长度

【LeetCode二叉树#07】左叶子节点之和(基于栈的迭代法前中后序遍历复习)的更多相关文章

  1. [C++] 非递归实现前中后序遍历二叉树

    目录 前置技能 需求描述 binarytree.h 具体实现 binarytree.cpp main.cpp 网上代码一搜一大片,大同小异咯. 书上的函数实现代码甚至更胜一筹,而且抄一遍就能用,唯一问 ...

  2. POJ 2255 Tree Recovery && Ulm Local 1997 Tree Recovery (二叉树的前中后序遍历)

    链接:poj.org/problem?id=2255 本文链接:http://www.cnblogs.com/Ash-ly/p/5463375.html 题意: 分别给你一个二叉树的前序遍历序列和中序 ...

  3. Binary Tree Traversal 二叉树的前中后序遍历

    [抄题]:二叉树前序遍历 [思维问题]: 不会递归.三要素:下定义.拆分问题(eg root-root.left).终止条件 [一句话思路]: 节点非空时往左移,否则新取一个点 再往右移. [输入量] ...

  4. C++二叉树前中后序遍历(递归&非递归)统一代码格式

    统一下二叉树的代码格式,递归和非递归都统一格式,方便记忆管理. 三种递归格式: 前序遍历: void PreOrder(TreeNode* root, vector<int>&pa ...

  5. Qt实现 动态化遍历二叉树(前中后层次遍历)

    binarytree.h 头文件 #ifndef LINKEDBINARYTREE_H #define LINKEDBINARYTREE_H #include<c++/algorithm> ...

  6. 二叉树前中后/层次遍历的递归与非递归形式(c++)

    /* 二叉树前中后/层次遍历的递归与非递归形式 */ //*************** void preOrder1(BinaryTreeNode* pRoot) { if(pRoot==NULL) ...

  7. C语言二叉树的创建、(先中后序)遍历以及存在的问题

    #include<stdlib.h> #include<stdio.h> #define True 1 #define False 0 typedef char TElemTy ...

  8. 飘逸的python - 极简的二叉树前中后序通杀函数

    对于任一结点.能够按某种次序运行三个操作: 訪问结点本身(N) 遍历该结点的左子树(L) 遍历该结点的右子树(R) 用来表示顺序,即,前序NLR/中序LNR/后序LRN. 以下我们用namedtupl ...

  9. Leetcode:105. 从前序与中序遍历序列构造二叉树&106. 从中序与后序遍历序列构造二叉树

    Leetcode:105. 从前序与中序遍历序列构造二叉树&106. 从中序与后序遍历序列构造二叉树 Leetcode:105. 从前序与中序遍历序列构造二叉树&106. 从中序与后序 ...

  10. 剑指offer面试题:输入某二叉树的前序遍历和中序遍历,输出后序遍历

    二叉树的先序,中序,后序如何遍历,不在此多说了.直接看题目描述吧(题目摘自九度oj剑指offer面试题6): 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结 ...

随机推荐

  1. Oracle 以及 达梦数据库简单查询所有表行数的存储过程

    1. 今天有一个场景需要查询一个数据库实例下面所有的表的行数. 本来想查询 user_tables 视图 但是发现 这个视图里面 达梦数据库 里面存的是null的.. 百度之后发现一个解决方案是 使用 ...

  2. 【python】SSTI模版注入

    0x00  Python Vene环境及介绍 venv虚拟环境:创建和管理虚拟环境的模块 首先apt update更新一下包管理 安装你当前版本的python-venv 选择一个目录,安装venv虚拟 ...

  3. 深度学习实践篇[17]:模型压缩技术、模型蒸馏算法:Patient-KD、DistilBERT、DynaBERT、TinyBERT

    深度学习实践篇[17]:模型压缩技术.模型蒸馏算法:Patient-KD.DistilBERT.DynaBERT.TinyBERT 1.模型压缩概述 1.2模型压缩原有 理论上来说,深度神经网络模型越 ...

  4. 驱动开发:内核封装TDI网络通信接口

    在上一篇文章<驱动开发:内核封装WSK网络通信接口>中,LyShark已经带大家看过了如何通过WSK接口实现套接字通信,但WSK实现的通信是内核与内核模块之间的,而如果需要内核与应用层之间 ...

  5. Win32汇编:数组与标志位测试总结

    整理复习汇编语言的知识点,以前在学习<Intel汇编语言程序设计 - 第五版>时没有很认真的整理笔记,主要因为当时是以学习理解为目的没有整理的很详细,这次是我第三次阅读此书,每一次阅读都会 ...

  6. C/C++ 通过Socket 传输结构体

    本质上socket无法传输结构体,我们只有将结构体装换为字节数组,或者是字符串格式来传输,到了服务端在强制类型转换一下即可,下面的代码分别提供原生写法与通过boost的实现两种,直接改改,可用于收集目 ...

  7. Java并发编程面试题

    Synchronized 用过吗,其原理是什么? Synchronized是jvm实现的一种互斥同步访问方式,底层是基于对象的监视器monitor实现的. 被synchronize修饰的代码在反编译后 ...

  8. 万字剖析OpenFeign整合Ribbon实现负载均衡的原理

    大家好,前面我已经剖析了OpenFeign的动态代理生成原理和Ribbon的运行原理,这篇文章来继续剖析SpringCloud组件原理,来看一看OpenFeign是如何基于Ribbon来实现负载均衡的 ...

  9. 架构设计脱胎换骨!英特尔酷睿Ultra深度解析

    英特尔正式发布了第一代酷睿Ultra处理器平台,也就是首个基于Intel 4制程工艺(7nm)打造的移动级处理器平台,其核心代号为Meteor Lake,产品系列贴标设计也采用了全新方案. 同时在命名 ...

  10. Web服务器实现|基于阻塞队列线程池的Http服务器|线程控制|Http协议

    基于阻塞队列生产者消费者模型线程池的多线程Web服务器 代码地址:WebServer_GitHub_Addr README 摘要 本实验通过C++语言,实现了一个基于阻塞队列线程池的多线程Web服务器 ...