110.平衡二叉树 (优先掌握递归)

给定一个二叉树,判断它是否是 平衡二叉树

平衡二叉树 是指该树所有节点的左右子树的深度相差不超过 1。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:

输入:root = [1,2,2,3,3,null,null,4,4]
输出:false

示例 3:

输入:root = []
输出:true

提示:

树中的节点数在范围 [0, 5000] 内

-104 <= Node.val <= 104


正解

既然要求比较高度,必然是要后序遍历。

  1. 明确递归函数的参数和返回值

    参数:当前传入节点。 返回值:以当前传入节点为根节点的树的高度。

    那么如何标记左右子树是否差值大于1呢?

    如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。

    所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。
  2. 明确终止条件

    递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0
  3. 明确单层递归的逻辑

    如何判断以当前传入节点为根节点的二叉树是否是平衡二叉树呢?当然是其左子树高度和其右子树高度的差值。

    分别求出其左右子树的高度,然后如果差值小于等于1,则返回当前二叉树的高度,否则返回-1,表示已经不是二叉平衡树了。
上代码(●'◡'●)
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;
return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);
}
bool isBalanced(TreeNode* root) {
return getHeight(root) == -1 ? false : true;
}
};

257. 二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]

示例 2:

输入:root = [1]
输出:["1"]

提示:

树中节点的数目在范围 [1, 100] 内

-100 <= Node.val <= 100


正解

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

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

  1. 递归函数参数以及返回值

    要传入根节点,记录每一条路径的path,和存放结果集的result,这里递归不需要返回值。
  2. 确定递归终止条件

    当 cur不为空,其左右孩子都为空的时候,就找到叶子节点。

    这里使用vector 结构path来记录路径,所以要把vector 结构的path转为string格式,再把这个string 放进 result里。

    那么为什么使用了vector 结构来记录路径呢? 因为在下面处理单层递归逻辑的时候,要做回溯,使用vector方便来做回溯。
  3. 确定单层递归逻辑

    因为是前序遍历,需要先处理中间节点,中间节点就是我们要记录路径上的节点,先放进path中。

    然后是递归和回溯的过程,上面说过没有判断cur是否为空,那么在这里递归的时候,如果为空就不进行下一层递归了。

    所以递归前要加上判断语句,下面要递归的节点是否为空

    此时还没完,递归完,要做回溯啊,因为path 不能一直加入节点,它还要删节点,然后才能加入新的节点。

    那么回溯要怎么回溯呢?

    我们知道,回溯和递归是一一对应的,有一个递归,就要有一个回溯。

    所以回溯要和递归永远在一起,世界上最遥远的距离是你在花括号里,而我在花括号外!
上代码(●'◡'●)
class Solution {
private: void traversal(TreeNode* cur, string path, vector<string>& result) {
path += to_string(cur->val); // 中
if (cur->left == NULL && cur->right == NULL) {
result.push_back(path);
return;
}
if (cur->left) traversal(cur->left, path + "->", result); // 左
if (cur->right) traversal(cur->right, path + "->", result); // 右
} public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
string path;
if (root == NULL) return result;
traversal(root, path, result);
return result; }
};

404.左叶子之和

给定二叉树的根节点 root ,返回所有左叶子之和。

示例 1:

输入: root = [3,9,20,null,null,15,7]
输出: 24
解释: 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24

示例 2:

输入: root = [1]
输出: 0

提示:

节点数在 [1, 1000] 范围内

-1000 <= Node.val <= 1000


首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。

左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点;

递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。

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

    判断一个树的左叶子节点之和,那么一定要传入树的根节点,递归函数的返回值为数值之和,所以为int

    使用题目中给出的函数就可以了。
  2. 确定终止条件

    如果遍历到空节点,那么左叶子值一定是0;

    注意,只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。 所以如果当前遍历的节点是叶子节点,那其左叶子也必定是0;
  3. 确定单层递归的逻辑

    当遇到左叶子节点的时候,记录数值,然后通过递归求取左子树左叶子之和,和 右子树左叶子之和,相加便是整个树的左叶子之和。
上代码(●'◡'●)
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == NULL) return 0;
int leftValue = 0;
if (root->left != NULL && root->left->left == NULL && root->left->right == NULL) {
leftValue = root->left->val;
}
return leftValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
};

写博不易,请大佬点赞支持一下8~

代码随想录Day15的更多相关文章

  1. 代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素

    第一题150. 逆波兰表达式求值 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 注意 两个整数之间的除法只保留整数部分. ...

  2. 代码随想录第八天 |344.反转字符串 、541. 反转字符串II、剑指Offer 05.替换空格 、151.翻转字符串里的单词 、剑指Offer58-II.左旋转字符串

    第一题344.反转字符串 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 s 的形式给出. 不要给另外的数组分配额外的空间,你必须原地修改输入数组.使用 O(1) 的额外空间解决这 ...

  3. 代码随想录-day1

    链表 今天主要是把链表专题刷完了,链表专题的题目不是很难,基本都是考察对链表的操作的理解. 在处理链表问题的时候,我们通常会引入一个哨兵节点(dummy),dummy节点指向原链表的头结点.这样,当我 ...

  4. 代码随想录 day0 博客怎么写

    前言 2.25日开始记录自己的博客生涯以及代码随想录训练营的每日内容 一.题目链接怎么找?怎么设置连接? 力扣题目链接1:力扣 二.正文怎么写? 二分查找 算法思路: 二分查找需要保证数组为有序数组同 ...

  5. 【LeetCode动态规划#05】背包问题的理论分析(基于代码随想录的个人理解,多图)

    背包问题 问题描述 背包问题是一系列问题的统称,具体包括:01背包.完全背包.多重背包.分组背包等(仅需掌握前两种,后面的为竞赛级题目) 下面来研究01背包 实际上即使是最经典的01背包,也不会直接出 ...

  6. 代码随想录第七天| 454.四数相加II、383. 赎金信 、15. 三数之和 、18. 四数之和

    第一题454.四数相加II 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, ...

  7. 代码随想录算法训练营day22 | leetcode 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点

    LeetCode 235. 二叉搜索树的最近公共祖先 分析1.0  二叉搜索树根节点元素值大小介于子树之间,所以只要找到第一个介于他俩之间的节点就行 class Solution { public T ...

  8. 代码随想录算法训练营day17 | leetcode ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和

    LeetCode 110.平衡二叉树 分析1.0 求左子树高度和右子树高度,若高度差>1,则返回false,所以我递归了两遍 class Solution { public boolean is ...

  9. 代码随想录算法训练营day13

    基础知识 二叉树基础知识 二叉树多考察完全二叉树.满二叉树,可以分为链式存储和数组存储,父子兄弟访问方式也有所不同,遍历也分为了前中后序遍历和层次遍历 Java定义 public class Tree ...

  10. 代码随想录算法训练营day10 | leetcode 232.用栈实现队列 225. 用队列实现栈

    基础知识 使用ArrayDeque 实现栈和队列 stack push pop peek isEmpty() size() queue offer poll peek isEmpty() size() ...

随机推荐

  1. 关于Collection和Map的笔记

    此二者在日常编程中,用得太频繁,所以多少有必要记录下,便于需要的时候翻翻. 但鉴于它们的后代太多,逐一牢记有有点难度,所以学习上应该把握以下几点即可: 含义 重要区别 常用的实现类和工具 关注要点:有 ...

  2. CLR via C# 笔记 -- 特性(18)

    1. 特性继承自System.Attribute,能作用于TypeDef(类.结构.枚举.接口和委托),MethodDef(含构造器),ParamDef,FieldDef,PropertyDef,Ev ...

  3. Linux 内核:设备驱动模型(5)平台设备驱动

    Linux 内核:设备驱动模型(5)平台设备驱动 背景 我们已经大概熟悉了Linux Device Driver Model:知道了流程大概是怎么样的,为了加深对LDDM框架的理解,我们继续来看pla ...

  4. STM32 学习:IAP有关介绍

    --- title: mcu-stm32-IAP-0-about date: 2020-05-27 08:51:58 categories: tags: - iap - stm32 - about - ...

  5. QT学习:08 QString

    --- title: framework-cpp-qt-08-QString EntryName: framework-cpp-qt-08-QString date: 2020-04-16 15:36 ...

  6. 阿里云日志Nginx日志分析

    每分钟接口访问次数的前200条统计 not request_uri : "/heartbeat.html" | SELECT time_series(time, '1m', '%H ...

  7. NXP i.MX 8M Plus工业核心板硬件说明书( 四核ARM Cortex-A53 + 单核ARM Cortex-M7,主频1.6GHz)

    1          硬件资源 创龙科技SOM-TLIMX8MP是一款基于NXP i.MX 8M Plus的四核ARM Cortex-A53 + 单核ARM Cortex-M7异构多核处理器设计的高端 ...

  8. Linux的访问权限详解

    题目 解读访问权限 rw-r--r--分别代表什么东西 r:代表可读 w:可写 e:可执行 方便起见进行拆分 rw- 代表文件所属用户的权限 r-- 代表同组用户的权限 r-- 代表其他用户的权限 同 ...

  9. Nginx使用upstream实现动静分离

    一.为什么要进行动静分离 分离资源,减少不必要到的请求消耗,减少请求延时. 注:我这里,是nginx处理静态资源,apache处理动态资源. 场景分析: 1.未分离之前的场景步骤 (1)客户端请求ur ...

  10. [WUSTCTF2020]朴实无华(命令执行)

    请求头问题 去查了一下资料了解了一下没有什莫用 robots.txt 中有东西 假flag 但是请求头里有重要消息 访问页面/fl4g.php <img src="/img.jpg&q ...