代码随想录刷题题Day14

刷题的第十四天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀
刷题语言:C++
Day14 任务
● 110.平衡二叉树
● 257. 二叉树的所有路径
● 404.左叶子之和

1 平衡二叉树

在这里插入图片描述

二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数
在这里插入图片描述

思路:
递归法
(1)明确递归函数的参数和返回值
参数:当前传入节点。 返回值:以当前传入节点为根节点的树的高度。

如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了

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

(2)明确终止条件:遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0

if (node == NULL) return 0;

(3)明确单层递归的逻辑

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

分别求出其左右子树的高度,然后如果差值小于等于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;

递归的函数传入节点指针,返回以该节点为根节点的二叉树的高度,如果不是二叉平衡树,则返回-1

求深度适合用前序遍历,而求高度适合用后序遍历
C++:
后序遍历

class Solution {
public:// 返回以该节点为根节点的二叉树的高度,如果不是平衡二叉树了则返回-1int 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;}
};

精简版本C++:

class Solution {
public: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;return abs(leftHeight - rightHeight) > 1 ? -1 : 1 + max(leftHeight, rightHeight);}bool isBalanced(TreeNode* root) {return getHeight(root) == -1 ? false : true;}
};

2 二叉树的所有路径

在这里插入图片描述
思路:

本道题要求根节点到叶子的路径,需要前序遍历,方便父节点指向孩子节点,找到对应的路径。

在这里插入图片描述
递归法:
(1)递归函数参数和返回值
参数:根节点、记录每一条路径的path、存放结果集的result。这里递归不需要返回值

void traversal(TreeNode* node, vector<int>& path, vector<string>& result)

(2)确定递归终止条件

本题要找到叶子节点,就开始结束的处理逻辑了(把路径放进result里)
找到叶子节点:当node不为空,左右孩子都为空的时候

if (node->left == NULL && node->right == NULL) {//终止处理逻辑
}

终止处理的逻辑:

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

使用vector 结构来记录路径,是因为在下面处理单层递归逻辑的时候,要做回溯,使用vector方便来做回溯

// 遇到叶子节点
if (node->left == NULL && node->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;
}

(3)确定单层递归逻辑

前序遍历,需要先处理中间节点,中间节点就是要记录路径上的节点,先放进path中
然后是递归和回溯的过程,上面说过没有判断node是否为空,那么在这里递归的时候,如果为空就不进行下一层递归了。
递归完,要做回溯,因为path 不能一直加入节点,它还要删节点,然后才能加入新的节点。

回溯和递归是一一对应的,有一个递归,就要有一个回溯

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

C++:

class Solution {
public:void traversal(TreeNode* node, vector<int>& path, vector<string>& result){path.push_back(node->val);// 中 最后一个节点也要加入到path中if (node->left == NULL && node->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);}if (node->left)// 左 {traversal(node->left, path, result);path.pop_back();// 回溯}if (node->right)// 右{traversal(node->right, path, result);path.pop_back();// 回溯}}vector<string> binaryTreePaths(TreeNode* root) {vector<int> path;vector<string> result;if (root == NULL) return result;traversal(root, path, result);return result;}
};

精简版本C++:

class Solution {
public:void traversal(TreeNode* node, string path, vector<string>& result){path += to_string(node->val); // 中if (node->left == NULL && node->right == NULL) {result.push_back(path);return;}if (node->left) traversal(node->left, path + "->", result); // 左if (node->right) traversal(node->right, path + "->", result); // 右}vector<string> binaryTreePaths(TreeNode* root) {vector<string> result;string path;if (root == NULL) return result;traversal(root, path, result);return result;}
};

vector类型的path,不管 每次 路径收集的数字是几位数,总之一定是int,所以就一次 pop_back就可以

3 左叶子之和

在这里插入图片描述
思路:

注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。
左叶子:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点

在这里插入图片描述
该左叶子之和为0,因为这棵树根本没有左叶子!
在这里插入图片描述
如果该节点的左节点不为空,该节点的左节点的左节点为空,该节点的左节点的右节点为空,则找到了一个左叶子

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

递归法:
递归的遍历顺序为后序遍历(左右中),需要通过递归函数的返回值累加求取左叶子数值之和
(1)确定递归函数的参数和返回值

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

(2)确定终止条件
遍历到空节点,那么左叶子值一定是0

if (root == NULL) return 0;

只有当前遍历的节点是父节点,才能判断其子节点是不是左叶子。 所以如果当前遍历的节点是叶子节点,那其左叶子也必定是0

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

(3)确定单层递归的逻辑

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

int leftNum = sumOfLeftLeaves(root->left);    // 左
if (root->left != NULL && root->left->left == NULL && root->left->right)
{leftNum = root->left->val;
}
int rightNum = sumOfLeftLeaves(root->right);  // 右
int sum = leftNum + rightNum;// 中
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 leftNum = sumOfLeftLeaves(root->left);// 左if (root->left != NULL && root->left->left == NULL && root->left->right == NULL)// 左子树就是一个左叶子的情况{leftNum = root->left->val;}int rightNum = sumOfLeftLeaves(root->right);// 右int sum = leftNum + rightNum;// 中return sum;}
};

精简C++:

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);}
};

鼓励坚持十五天的自己😀😀😀

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

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

相关文章

Unity项目优化案例二

本文地址&#xff1a;https://blog.csdn.net/t163361/article/details/135024136 针对工作中遇到的优化问题&#xff0c;记录一下&#xff0c;给大家优化自己的项目提供一些思路。 公司产品最近正给国内某大型赛事做支撑服务暴露出不少问题。 使用环境 Unity 2021.3.0f1 cpu…

新手HTML和CSS的常见知识点

​​​​ 目录 1.HTML标题标签&#xff08;到&#xff09;用于定义网页中的标题&#xff0c;并按照重要性递减排列。例如&#xff1a; 2.HTML段落标签&#xff08;&#xff09;用于定义网页中的段落。例如&#xff1a; 3.HTML链接标签&#xff08;&#xff09;用于创建链接…

报错Cannot read property delayMs of null;【Bug已解决-鸿蒙应用开发】

文章目录 项目场景:问题描述原因分析:解决方案:此Bug解决方案总结附录-相关知识鸿蒙应用开发优势鸿蒙操作系统应用场景项目场景: 应用开发时报错: Cannot read property delayMs of null; 分析一下是什么错误原因导致的?下文详细描述 问题描述 相关问题: 应用开发时…

【字节笔试题】大小为n的数组中有多少个连续子数组满足该子数组所有元素的乘积是k的倍数?

题目描述 小红拿到了一个大小为n的数组&#xff0c;他想知道&#xff0c;有多少连续子数组满足&#xff0c;该子数组所有元素的乘积是k的倍数&#xff1f; 输入输出 第一行输入2个整数&#xff0c;分别是数组长度n和参数k 第二行输入n个元素的数组 n有10^5级别 数组元素有1…

2021年数维杯国际大学生数学建模A题新冠肺炎背景下港口资源优化配置策略求解全过程文档及程序

2021年数维杯国际大学生数学建模 A题 新冠肺炎背景下港口资源优化配置策略 原题再现&#xff1a; 2020年初&#xff0c;新型冠状病毒&#xff08;COVID-19&#xff09;在全球迅速蔓延。根据世界卫生组织2021年7月31日的报告&#xff0c;新冠病毒疫情对人类的影响可能比原先预…

Tomcat-安装部署(源码包安装)

一、简介 Tomcat 是由 Apache 开发的一个 Servlet 容器&#xff0c;实现了对 Servlet 和 JSP 的支持&#xff0c;并提供了作为Web服务器的一些特有功能&#xff0c;如Tomcat管理和控制平台、安全域管理和Tomcat阀等。 简单来说&#xff0c;Tomcat是一个WEB应用程序的托管平台…

安装升级备份卸载 Grafana

要在 RHEL 或 Fedora 上卸载 Grafana&#xff0c;请按照以下步骤操作&#xff1a; 如果您配置了 Grafana 使用 systemd&#xff0c;请停止 Grafana 服务器的 systemd 服务&#xff1a; sudo systemctl stop grafana-server如果您配置了 Grafana 使用 init.d&#xff0c;请停止 …

【MySQL学习之基础篇】约束

文章目录 1. 概述2. 基础约束3. 外键约束3.1. 介绍3.2. 外键的添加3.3. 外键删除和更新行为 1. 概述 概念&#xff1a; 约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。     目的&#xff1a; 保证数据库中数据的正确、有效性和完整性。 分类&#x…

Django使用UUID作为主键

Django这个框架&#xff0c;如果你在定义模型时没有显式的指定主键&#xff0c;那么它会贴心的送你一个自增的id主键&#xff1a; class SomeModel(model.Model):# 下面这个 id 字段是不需要写的&#xff0c;django 自动附送# id models.AutoField(primary_keyTrue)... 这个…

BearPi Std 板从入门到放弃 - 先天神魂篇(7)(RT-Thread 定时器-软件定时器)

简介 RT-Thread 软件定时器的简单使用步骤 创建项目 参考 BearPi RT-Thread项目创建 定时器管理接口 定时器时钟节拍 定时器管理相关函数 定时器类型 #define RT_TIMER_FLAG_ONE_SHOT 0x0 //一次性计时器 #define RT_TIMER_FLAG_PERIODIC 0x2 // 周期性定时器 #…

【Docker】ES、Kibana及IK安装配置

目录 一.单节点安装部署 1.版本选择 2.推荐及总结 ​3.官网下载地址 4.创建网络 5.拉取镜像 6.创建文件夹 7.运行docker命令 二、安装kibana 1.安装kibana 2.浏览器访问 3.国际化 三、Elasticsearch查询 1.数据插入&#xff1a;POST或PUT 2.数据查询GET 3.分词…

如何用Adobe Audition 检测波形的pop和卡顿

在Adobe Audition中&#xff0c;检测卡顿和pop的方法各有不同&#xff1a; 1. **检测卡顿**&#xff1a; - 使用“诊断”面板中的“删除静音”或“标记音频”选项可以帮助识别音频中的静音段落&#xff0c;这可能表明存在卡顿。 - 配置诊断设置&#xff0c;指定静音的振…

docker consul容器的自动发现与注册

一、微服务&#xff08;容器&#xff09;的注册与发现——微服务架构中极其重要的组件 1、定义&#xff1a;是一种分布式管理系统以及定位服务的方法。传统架构中&#xff0c;应用程序之间直连到已知的服务&#xff0c;设备提供的网络&#xff08;IP地址&#xff09;&#xff…

高级前端开发工程师

岗位需求 熟练掌握前端主流框架Vue、React、Angular,至少熟练掌控Vue全家桶 文章目录 岗位需求前言一、Vue框架二、React框架三、Angular框架四、什么是Vue全家桶前言 -那就看你表哥的电脑里有没有硬盘 -我不敲键盘 一、Vue框架 Vue(读音为/vjuː/,类似于"view"…

Linux 内存池源码剖析

1 传统的分配与释放内存的函数缺点: void *malloc(size_t size); void *calloc(size_t nmemb,size_t size);void *realloc(void *ptr, size_t size);void free(void *ptr);缺点1: 高并发时较小内存块使用导致系统调用频繁,降低了系统的执行效率 缺点2: 频繁使用时增加了系统…

【.Net 6.0--通用帮助类--EmailHelper】

前言 邮件帮助类&#xff08;smtp协议&#xff09;&#xff0c;需要NuGet引用MailKit包&#xff0c;包含了同步发送邮件&#xff08;SendEmail)、异步发送邮件&#xff08; SendEmailAsync&#xff09;方法&#xff0c;由于非企业邮箱每日有发送限额&#xff0c;故代码中支持轮…

(C语言)精确计算程序运行时间的方法

一、先计算每秒多少个计数 typedef __int64 s64;s64 tps; /* timestamp counter per second */s64 get_tps(void) {s64 t0 rdtsc();Sleep(100);return (rdtsc() - t0) * 10; } 这段代码定义了一个函数 get_tps&#xff0c;该函数用于测量处理器的时间戳计数器&#xff08;RD…

【答案】2023年国赛信息安全管理与评估第三阶段夺旗挑战CTF(网络安全渗透)

【答案】2023年国赛信息安全管理与评估第三阶段夺旗挑战CTF&#xff08;网络安全渗透&#xff09; 全国职业院校技能大赛高职组信息安全管理与评估 &#xff08;赛项&#xff09; 评分标准 第三阶段 夺旗挑战CTF&#xff08;网络安全渗透&#xff09; *竞赛项目赛题* 本文…

柔性数组(结构体成员)

目录 前言&#xff1a; 柔性数组&#xff1a; 给柔性数组分配空间&#xff1a; 调整柔性数组大小&#xff1a; 柔性数组的好处&#xff1a; 前言&#xff1a; 柔性数组&#xff1f;可能你从未听说&#xff0c;但是确实有这个概念。听名字&#xff0c;好像就是柔软的数…

如何连接到 Azure SQL 数据库(下)

在《如何连接到 Azure SQL 数据库&#xff08;上&#xff09;》中&#xff0c;我们已经了解到了以下内容↓↓↓ 开始之前&#xff1a;Azure 连接凭据和防火墙 如何检索 Azure 连接凭据如何配置服务器防火墙使用 SQL Server Management Studio 连接到 Azure使用 dbForge Studio…