代码随想录刷题题Day15

刷题的第十五天,希望自己能够不断坚持下去,迎来蜕变。😀😀😀
刷题语言:C++
Day15 任务
● 513.找树左下角的值
● 112. 路径总和 113.路径总和ii
● 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

1 找树左下角的值

在这里插入图片描述
本题要找出树的最后一行最左边的值
思路1:层序遍历
思路2:递归

迭代法
层序遍历模板参考代码随想录刷题题Day12

class Solution {
public:int findBottomLeftValue(TreeNode* root) {queue<TreeNode*> que;int result;if (root != NULL) que.push(root);while (!que.empty()){int size = que.size();for (int i = 0; i < size; i++){TreeNode* node = que.front();que.pop();if (i == 0) result = node->val;// 记录最后一行第一个元素if (node->left) que.push(node->left);if (node->right) que.push(node->right);}}return result;}
};

递归法

误区:不是一直向左遍历,最后一个就是答案
一直向左遍历到最后一个,未必是最后一行

关键:在树的最后一行找到最左边的值

(1) 判断最后一行:深度最大的叶子节点
(2) 最左边的值:可以使用前序遍历(当然中序,后序都可以,因为本题没有 中间节点的处理逻辑,只要左优先就行),保证优先左边搜索,然后记录深度最大的叶子节点,此时就是树的最后一行最左边的值。

(1)确定递归函数的参数和返回值
参数:要遍历的树的根节点,最长深度
返回值:void

int maxDepth = INT_MIN;// 全局变量 记录最大深度
int result;            // 全局变量 最大深度最左节点的数值
void traversal(TreeNode* node, int depth)

(2)确定终止条件

当遇到叶子节点的时候,就需要统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度。

if (node->left == NULL && node->right == NULL)
{if (depth > maxDepth){maxDepth = depth;   // 更新最大深度result = node->val; // 最大深度最左面的数值}return;
}

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

找最大深度的时候,递归的过程中依然要使用回溯

// 中
if (node->left) {// 左depth++;// 深度加一traversal(node->left, depth);depth--;// 回溯,深度减一
}
if (node->right) {// 右depth++;// 深度加一traversal(node->right, depth);depth--;// 回溯,深度减一
}

C++:

class Solution {
public:int maxDepth = INT_MIN;int result;void traversal(TreeNode* node, int depth) {if (node->left == NULL && node->right == NULL) {if (maxDepth < depth) {maxDepth = depth;result = node->val;}}if (node->left) {depth++;traversal(node->left, depth);depth--;}if (node->right) {depth++;traversal(node->right, depth);depth--;}return;}int findBottomLeftValue(TreeNode* root) {traversal(root, 0);return result;}
};

精简版本C++:

class Solution {
public:int maxDepth = INT_MIN;int result;void traversal(TreeNode* node, int depth) {if (node->left == NULL && node->right == NULL) {if (maxDepth < depth) {maxDepth = depth;result = node->val;}}if (node->left) {traversal(node->left, depth + 1);// 隐藏着回溯}if (node->right) {traversal(node->right, depth + 1);// 隐藏着回溯}return;}int findBottomLeftValue(TreeNode* root) {traversal(root, 0);return result;}
};

2 路径总和

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

使用深度优先遍历的方式,本题前中后序都可以,因为中间节点没有处理逻辑

递归法
(1)确定递归函数的参数和返回类型

参数:二叉树的根节点、计算器(用来计算二叉树的一条边之和是否正好是目标和)
返回值:要找一条符合条件的路径,所以递归函数需要返回值,遍历的路线,并不要遍历整棵树,及时返回,返回类型是bool
在这里插入图片描述

递归函数返回值:
(1)如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值
(2)如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
(3)如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回

bool traversal(TreeNode* node, int count)

(2)确定终止条件

计数器count初始为目标和,然后每次减去遍历路径节点上的数值

  1. 如果最后count == 0,同时到了叶子节点的话,说明找到了目标和
  2. 如果遍历到了叶子节点,count不为0,就是没找到
if (node->left == NULL && node->right == NULL && count == 0) return true;
if (node->left == NULL && node->right == NULL && count != 0) return false;

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

递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回

if (node->left) {// 左 (空节点不遍历)// 遇到叶子节点返回true,则直接返回trueif (traversal(node->left, count - node->left->val)) return true;
}
if (node->right) {// 右 (空节点不遍历)// 遇到叶子节点返回true,则直接返回trueif (traversal(node->right, count - node->right->val)) return true;
return false;

把回溯的过程表现出来:

if (node->left) {// 左count -= node->left->val;// 递归,处理节点;if (traversal(node->left, count)) return true;count += node->left->val;// 回溯,撤销处理结果
}
if (node->right) { // 右count -= node->right->val;if (traversal(node->right, count)) return true;count += node->right->val;// 回溯,撤销处理结果
}

C++:

class Solution {
public:bool traversal(TreeNode* node, int count) {if (node->left == NULL && node->right == NULL && count == 0) return true;// 遇到叶子节点,并且计数为0if (node->left == NULL && node->right == NULL && count != 0) return false;// 遇到叶子节点直接返回if (node->left) {// 左count -= node->left->val;// 递归,处理节点;if (traversal(node->left, count)) return true;count += node->left->val;// 回溯,撤销处理结果}if (node->right) {// 右count -= node->right->val;// 递归,处理节点if (traversal(node->right, count)) return true;count += node->right->val;// 回溯,撤销处理结果}return false;}bool hasPathSum(TreeNode* root, int targetSum) {if (root == NULL) return false;return traversal(root, targetSum - root->val);}
};

精简版本C++:

class Solution {
public:bool hasPathSum(TreeNode* root, int targetSum) {if (!root) return false;if (!root->left && !root->right && targetSum == root->val) {return true;}return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);}
};

在这里插入图片描述
思路:
路径总和ii要遍历整个树,找到所有路径,所以递归函数不要返回值
在这里插入图片描述

class Solution {
public:vector<vector<int>> result;vector<int> path;// 递归函数不需要返回值,因为我们要遍历整个树void traversal(TreeNode* node, int count) {if (node->left == NULL && node->right == NULL && count == 0) {result.push_back(path);return;}if (node->left == NULL && node->right == NULL) return;// 遇到叶子节点而没有找到合适的边,直接返回if (node->left) {// 左 (空节点不遍历)path.push_back(node->left->val);count -= node->left->val;traversal(node->left, count);// 递归count += node->left->val;// 回溯path.pop_back();// 回溯}if (node->right) {// 右 (空节点不遍历)path.push_back(node->right->val);count -= node->right->val;traversal(node->right, count);// 递归count += node->right->val;// 回溯path.pop_back();// 回溯}return;}vector<vector<int>> pathSum(TreeNode* root, int targetSum) {result.clear();path.clear();if (root == NULL) return result;path.push_back(root->val);// 把根节点放进路径traversal(root, targetSum - root->val);return result;}
};

3 从中序与后序遍历序列构造二叉树

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

  1. 后序数组为0,空节点
  2. 后序数组最后一个元素为节点元素
  3. 寻找中序数组位置作为切割点
  4. 切中序数组
  5. 切后序数组
  6. 递归处理左右区间

在这里插入图片描述
C++:

class Solution {
public:TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {if (postorder.size() == 0) return NULL;// 后序遍历数组最后一个元素,就是当前的中间节点int rootValue = postorder[postorder.size() - 1];TreeNode* root = new TreeNode(rootValue);// 叶子节点if (postorder.size() == 1) return root;// 找到中序遍历的切割点int index;for (index = 0; index < inorder.size(); index++){if (inorder[index] == rootValue) break;}// 切割中序数组vector<int> leftInorder(inorder.begin(), inorder.begin() + index);vector<int> rightInorder(inorder.begin() + index + 1, inorder.end());postorder.resize(postorder.size() - 1);// 切割后序数组vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());root->left = traversal(leftInorder, leftPostorder);root->right = traversal(rightInorder, rightPostorder);return root;}TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {if (inorder.size() == 0 || postorder.size() == 0) return NULL;return traversal(inorder, postorder);}
};

4 从前序与中序遍历序列构造二叉树

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

  1. 前序数组为0,空节点
  2. 前序数组第一个元素为节点元素
  3. 寻找中序数组位置作为切割点
  4. 切中序数组
  5. 切前序数组
  6. 递归处理左右区间

C++:

class Solution {
public:TreeNode* traversal(vector<int>& preorder, vector<int>& inorder) {// 前序数组为0,空节点if (preorder.size() == 0) return NULL;// 前序数组第一个元素为节点元素int rootValue = preorder[0];TreeNode* root = new TreeNode(rootValue);if (preorder.size() == 1) return root;// 寻找中序数组位置作为切割点int index;for (index = 0; index < inorder.size(); index++) {if (inorder[index] == rootValue) break;}// 切中序数组vector<int> leftInorder(inorder.begin(), inorder.begin() + index);vector<int> rightInorder(inorder.begin() + index + 1, inorder.end());// 切前序数组preorder.erase(preorder.begin());vector<int> leftPreorder(preorder.begin(), preorder.begin() + leftInorder.size());vector<int> rightPreorder(preorder.begin() + leftPreorder.size(), preorder.end());// 递归处理左右区间root->left = traversal(leftPreorder, leftInorder);root->right = traversal(rightPreorder, rightInorder);return root;}TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if (preorder.size() == 0 || inorder.size() == 0) return NULL;return traversal(preorder, inorder);}
};

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

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

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

相关文章

MYSQL备份和恢复

数据库的备份和恢复&#xff1a; 备份&#xff1a;完全备份 增量备份 完全备份&#xff1a;将整个数据库完整的进行备份 增量备份&#xff1a;在完全备份的基础之上&#xff0c;对后续新增的内容进行备份 备份的需求&#xff1a; 在生产环境中&#xff0c;数据的安全至关重…

Docker安装Redis哨兵

目录 Redis哨兵 一、哨兵模式的主要概念和组件 二、哨兵模式的工作流程 三、哨兵配置流程 1、创建Redis哨兵配置文件 2、启动哨兵 3、命令解读 4、 查看哨兵是否正常启动 5、测试主机宕机 四、哨兵运行流程 五、哨兵选举算法 六、哨兵使用建议 Redis哨兵 Redis哨兵…

josef约瑟 时间继电器 DS-23/C AC220V 10S柜内板前接线

系列型号&#xff1a; DS-21时间继电器 &#xff1b;DS-22时间继电器&#xff1b; DS-23时间继电器&#xff1b;DS-24时间继电器&#xff1b; DS-21C时间继电器&#xff1b;DS-22C时间继电器&#xff1b; DS-23C时间继电器&#xff1b; DS-25时间继电器&#xff1b;DS-26…

python/c++ Leetcode题解——746. 使用最小花费爬楼梯

目录 方法一&#xff1a;动态规划 复杂度分析 方法一&#xff1a;动态规划 假设数组 cost 的长度为 n&#xff0c;则 n 个阶梯分别对应下标 0 到 n−1&#xff0c;楼层顶部对应下标 n&#xff0c;问题等价于计算达到下标 n 的最小花费。可以通过动态规划求解。 创建长度为 n…

springboot 学习网站

Spring Boot 系列教程https://www.docs4dev.com/ Spring Boot 教程汇总 http://www.springboot.wiki/ Spring Cloud 微服务教程 http://www.springboot.wiki/ 1、自定义banner   https://www.cnblogs.com/cc11001100/p/7456145.html 2、事件和监听器   https://blog.csd…

孩子都能学会的FPGA:第三十三课——用FPGA实现一个通用的SPI主机接收模块

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…

如何从 iPhone 上恢复已删除的照片教程分享

您是否错误地删除了 iPhone 上的错误照片&#xff1f;或者您可能已将手机恢复出厂设置&#xff0c;但现在所有照片都消失了&#xff1f;如果您现在遇到这样的情况&#xff0c;我们可以为您提供解决方案。 在本文中&#xff0c;我们将向您展示七种数据恢复方法&#xff0c;可以…

人工智能驱动化学品创新设计的实践与展望

改进化学品研发模式&#xff0c;缩短化学品从发现到应用的时间是化工行业中所有科学研究者和产业人员的最终目 标。本文提出&#xff1a;化学品设计是一个涉及多组分、多尺度和多物理场的复杂过程&#xff0c;现有的实验研究模式难以深入高 效地揭示相关的物理化学机制&#xf…

STM8L151C8单片机学习例程(9)——Unique-ID

直接点击打不开&#xff0c;右键新建窗口打开链接 STM8L151C8单片机学习例程&#xff08;7&#xff09;——Unique-ID

论文解读 | NeurIPS2023:「解释一切」图像概念解释器

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 讲者简介 孙奥&#xff1a; 香港科技大学软件安全实验室在读博士&#xff0c;研究兴趣为可解释性人工智能和可信机器学习&#xff0c;主要是从Post-hoc&#xff0c;逻辑和概念的角度分析神经网络的机理 Title 「…

服务器安全的威胁和防范

由于服务器发挥着至关重要的作用&#xff0c;因此存储在服务器上的机密数据和信息非常具有价值。做好服务器安全至关重要。 常见的服务器安全隐患包括&#xff1a; 1.恶意的攻击&#xff1a;遭受CC攻击和DDoS攻击&#xff0c;导致游戏或是网站打不开&#xff0c;严重影响业务…

【智能算法】11种混沌映射算法+2种智能算法示范【鲸鱼WOA、灰狼GWO算法】

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 混沌映射算法是我们在智能算法改进中常用到的方法&#xff0c;本程序充分考虑改进算法应用的便捷性&#xff0c;集成了11种混合映射算法&#xff0c;包括Singer、tent、Logistic、Cubic、chebyshev、Piecewise…

学通python

学通python &#xff08;一. 涉及知识点&#xff09; python基础&#xff08;认识python&#xff0c;环境&#xff0c;pycharm&#xff0c;注释&#xff0c;变量&#xff0c;变量类型&#xff0c;输入输出&#xff0c;运算发&#xff09;流程控制结构&#xff08;判断语句&am…

华为面试题,连续出了三年!

写在前面 据说&#xff0c;这是一道被华为 2021、2022 和 2023 都出过的题目 &#x1f923; 华为是「卷」的发明者&#xff0c;但不是「内卷」发明者&#xff0c;毕竟只有华为是实打实的给加班费。 这么卷的公司&#xff0c;怎么也不更新一下题库。 难道没人做出来就不用考虑换…

2023-12-17 AIGC-AnimateDiff详细安装和使用教程

AnimateDiff专用模型下载 AnimateDiff有其自身专门的运动模型mm_sd_v15_v2.ckpt 和 专属的镜头运动lora,需要放置在对应的位置。 stablediffusion位置: 运动模型放在stable-diffusion-webui\extensions\sd-webui-animatediff\model里面 运动lora放在stable-diffusion-web…

Spring源码学习三

手写Starter 我们通过手写Starter来加深对于自动装配的理解 1.创建一个Maven项目&#xff0c;quick-starter 定义相关的依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><versio…

通过conda search cuda找不到想要的信息,更换channel

目录 1. 通过conda search cuda找不到想要的信息&#xff0c;更换channel2. 不添加channel&#xff0c;直接conda search cudnn -i https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/报错了3. 推荐几个channel4. 想通过conda search应用这些channel&#xff0c;请给出…

etcd是什么

目录 1.关于etcd2.应用场景 本文主要介绍etcd 概念和基本应用场景。 1.关于etcd etcd是一个开源的、分布式的键值存储系统&#xff0c;用于共享配置和服务发现。它是由CoreOS团队开发的&#xff0c;主要用于实现分布式系统的配置管理和服务发现。 etcd的主要特性包括&#x…

Quartus 18.1软件及支持包安装教程

安装前最好关闭电脑的杀毒软件和防火墙 安装包可以到Quartus官网下载需要的版本&#xff0c;注意选择操作系统 Quartus官网&#xff1a;FPGA 设计软件 - 英特尔 Quartus Prime (intel.cn) 下载解压后以管理员的身份运行 QuartusSetup-18.1.0.625.exe文件&#xff0c;版本不同…

中国剩余定理CRT

文章目录 作用证明AcWing 204. 表达整数的奇怪方式CODE 作用 用于求模数两两互质的线性同余方程组&#xff0c;若不互质则不存在解。 《孙子算经》中有这样一个问题&#xff1a;“今有物不知其数&#xff0c;三三数之剩二&#xff0c;五五数之剩三&#xff0c;七七数之剩二&am…