代码随想录刷题题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,一经查实,立即删除!

相关文章

新手HTML和CSS的常见知识点

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

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应用程序的托管平台…

【MySQL学习之基础篇】约束

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

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: 频繁使用时增加了系统…

【答案】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…

数据结构--稀疏矩阵及Java实现

一、稀疏 sparsearray 数组 1、先看一个实际的需求 编写的五子棋程序中&#xff0c;有存盘退出和续上盘的功能。 分析问题: 因为该二维数组的很多值是默认值 0, 因此记录了很多没有意义的数据.->稀疏数组。 2、稀疏数组基本介绍 当一个数组中大部分元素为&#xff10;…

wordpress安装之正式开始安装wordpress

1、拉取wordpress镜像 docker pull wordpress 2、启动容器 启动容器&#xff0c;设置容器名为wordpress2并把80端口映射到宿主机的9988端口 docker run -it --name wordpress2 -p 9988:80 -d wordpress 3、查看容器状态 docker ps 4、安装wordpress博客程序 因为我们前面启…

微信小程序---使用npm包安装Vant组件库

在小程序项目中&#xff0c;安装Vant 组件库主要分为如下3步: 注意&#xff1a;如果你的文件中不存在pakage.json&#xff0c;请初始化一下包管理器 npm init -y 1.通过 npm 安装(建议指定版本为1.3.3&#xff09; 通过npm npm i vant/weapp1.3.3 -S --production 通过y…

大数据技术14:FlinkCDC数据变更捕获

前言&#xff1a;Flink CDC是Flink社区开发的flink-cdc-connectors 组件&#xff0c;这是⼀个可以直接从 MySQL、PostgreSQL 等数据库直接读取全量数据和增量变更数据的 source 组件。 https://github.com/ververica/flink-cdc-connectors 一、CDC 概述 CDC 的全称是 Change …

换内核ubuntu

grep menuentry /boot/grub/grub.cfg我要使用第三个(索引从0开始&#xff0c;所以是第二个) 可以使用vi编辑&#xff08;很麻烦&#xff09; i变为插入模型 esc变为普通模型 &#xff1a;x删除单个字符&#xff0c;dd删除一行&#xff0c;&#xff1a;wq保存并退出 更新文件…

rabbitmq-windows安装使用-简易后台界面-修改密码

文章目录 1.下载2.安装3.安装 RabbitMQ4.后台访问5.修改密码 1.下载 将erlang运行时和rabbitmq-windows版本&#xff0c;上传在csdn&#xff0c;下载链接。https://download.csdn.net/download/m0_67316550/88633443 2.安装 右键&#xff0c;以管理员身份运行rabbitmq。启动…

Android 12.0 Launcher3定制化之动态时钟图标功能实现

1.概述 在12.0的系统产品rom定制化开发中,在Launcher3中的定制化的一些功能中,对于一些产品要求需要实现动态时钟图标功能,这就需要先绘制时分秒时针表盘,然后 每秒刷新一次时钟图标,时钟需要做到实时更新,做到动态时钟的效果,接下来就来分析这个功能的实现 如图: 2.动…