代码随想录第十八天 513 找树左下角的值 112 路径之和 106 从中序与后序遍历序列构造二叉树

LeetCode 513 找树左下角的值 

题目描述

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

示例 1:

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

示例 2:

输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7

思路 

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

参数必须有要遍历的树的根节点,还有就是一个int型的变量用来记录最长深度。 这里就不需要返回值了,所以递归函数的返回类型为void。

本题还需要类里的两个全局变量,maxLen用来记录最大深度,result记录最大深度最左节点的数值。

代码如下:

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

      2.确定终止条件

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

代码如下:

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

      3.确定单层递归的逻辑

在找最大深度的时候,递归的过程中依然要使用回溯,代码如下:

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

代码实现  

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:int maxDepth = INT_MIN;int result;void traversal(TreeNode* root,int depth){if(root -> left == NULL && root -> right == NULL){if(depth > maxDepth){maxDepth = depth;result = root -> val;}return;     }if(root -> left){depth++;traversal(root -> left,depth);depth--;}if(root -> right){depth++;traversal(root -> right,depth);depth--;}return;}int findBottomLeftValue(TreeNode* root) {int depth;traversal(root,depth);return result;}
};

LeetCode 112 路径之和 

 题目描述

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

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

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

 思路

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

参数:需要二叉树的根节点,还需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。

再来看返回值,递归函数什么时候需要返回值?什么时候不需要返回值?这里总结如下三点:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)

而本题我们要找一条符合条件的路径,所以递归函数需要返回值,及时返回,那么返回类型是什么呢?

如图所示:

112.路径总和

图中可以看出,遍历的路线,并不要遍历整棵树,所以递归函数需要返回值,可以用bool类型表示。

所以代码如下:

bool traversal(treenode* cur, int count)   // 注意函数的返回类型

2.确定终止条件

首先计数器如何统计这一条路径的和呢?

不要去累加然后判断是否等于目标和,那么代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。

如果最后count == 0,同时到了叶子节点的话,说明找到了目标和。

如果遍历到了叶子节点,count不为0,就是没找到。

递归终止条件代码如下:

if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找到合适的边,直接返回

     3.确定单层递归的逻辑

因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。

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

代码如下:

if (cur->left) { // 左 (空节点不遍历)// 遇到叶子节点返回true,则直接返回trueif (traversal(cur->left, count - cur->left->val)) return true; // 注意这里有回溯的逻辑
}
if (cur->right) { // 右 (空节点不遍历)// 遇到叶子节点返回true,则直接返回trueif (traversal(cur->right, count - cur->right->val)) return true; // 注意这里有回溯的逻辑
}
return false;

 代码实现

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

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

题目描述

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

示例 1:

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

示例 2:

输入:inorder = [-1], postorder = [-1]
输出:[-1]

思路

中序:9 3 15 20 7   左中右

后续:9 15 7 20 3  左右中

遍历二叉树的思路是,首先后续数组的最后一个元素一定是根节点,找到根节点之后切割中序数组,根节点前面的数组为左子树,后面的为右子树。根据中序数组左子树和右子树的元素个数,切割后序数组,例如左子树一共有3个数字,那么后续数组的前三个元素就是左子树,第四个到第size-1个就是右子树,然后再找后序数组左子树和右子树的最后一个元素,这个元素就是左子树或右子树的中间节点。依此类推,中间节点左右两边的数据再分为左子树和右子树,直到所有元素都遍历了为止。

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

代码思路如下:

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

  • 第五步:切割后序数组,切成后序左数组和后序右数组

  • 第六步:递归处理左区间和右区间

代码实现

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* buildTree(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 = 0;for(index = 0;index < inorder.size();index++){if(inorder[index] == rootvalue) break; }vector<int> leftinorder;vector<int> rightinorder;vector<int> leftpostorder;vector<int> rightpostorder;for(int i = 0;i < index;i++){leftpostorder.push_back(postorder[i]);} for(int i = index;i < postorder.size()-1;i++){rightpostorder.push_back(postorder[i]);}for(int i = 0;i < index;i++){leftinorder.push_back(inorder[i]);}for(int i = index+1;i < postorder.size();i++){rightinorder.push_back(inorder[i]);}root -> left = buildTree(leftinorder,leftpostorder);root -> right = buildTree(rightinorder,rightpostorder);return root;}
};

ps:这里已知前序,中序或者中序,后序都可以构造唯一的二叉树,但是前序和后序不可以,因为前序和后序的左子树,右子树都是相连的,不可以构造唯一的二叉树。

LeetCode  654 最大二叉树

题目描述 

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边 的 子数组前缀上 构建左子树。
  3. 递归地在最大值 右边 的 子数组后缀上 构建右子树。

返回 nums 构建的 最大二叉树 

示例 1:

输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。- 空数组,无子节点。- [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。- 空数组,无子节点。- 只有一个元素,所以子节点是一个值为 1 的节点。- [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。- 只有一个元素,所以子节点是一个值为 0 的节点。- 空数组,无子节点。

示例 2:

输入:nums = [3,2,1]
输出:[3,null,2,null,1]

思路

本题的思路和上一题的思路基本一致,刚开始没有判断nums的size是否为0,会有如下报错。

刚开始的nums不为空,递归几轮之后可能数组就会为空,所以还是要判断,size为1也要判断。

代码实现

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* constructMaximumBinaryTree(vector<int>& nums) {if(nums.size() == 0) return NULL;int maxvalue = 0;int maxindex;for(int i = 0;i < nums.size();i++){if(nums[i] > maxvalue){maxvalue = nums[i];maxindex = i;}}TreeNode* root = new TreeNode(maxvalue);if(nums.size() == 1) return root;vector<int> lefttree;vector<int> righttree;for(int i = 0;i < maxindex;i++){lefttree.push_back(nums[i]);}for(int i = maxindex+1;i < nums.size();i++){righttree.push_back(nums[i]);}root -> left = constructMaximumBinaryTree(lefttree);root -> right = constructMaximumBinaryTree(righttree);return root;}
};

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

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

相关文章

MySQL用户管理

1.用户 1.1 用户信息 mysql> use mysql; Database changed mysql> select host,user,authentication_string from user; --------------------------------------------------------------------- | host | user | authentication_string | --…

ubuntu 20.04 aarch64 平台交叉编译 libffi 库

前言 由于打算交叉编译 python&#xff0c;但是依赖 libffi 库&#xff0c;也就是 libffi 库也需要交叉编译 环境&#xff1a; ubuntu 20.04 交叉编译工具链&#xff1a;这里使用 musl libc 的 gcc 交叉编译工具链&#xff0c;aarch64-linux-musleabi-gcc&#xff0c;gcc 版本…

智谱AI官网再升级,GLM-4,智能体,AI作图长文档全部搞定

创建智能体 智能体体验中心 可以看到智谱AI也推出了自己的智能体&#xff0c;并且官方内置了丰富多样的智能体供大家免费体验。 GLM-4 原生支持自动联网、图片生成、数据分析等复杂任务&#xff0c;现开放体验中&#xff0c;快来开启更多精彩。写一篇《繁花》的影评&#xf…

[每日一题] 01.23 - 画矩形

画矩形 height,width,c,d input().split() height,width,d int(height),int(width),int(d) lis [c * width if d else c * (width - 2) c for i in range(height) ]lis: ##### # # # # ##### 或 # # # # # # # #if not d:print(c * width)for i in lis[1:-1…

1986-Minimum error thresholding

1 论文简介 《Minimum error thresholding》是由 Kittler 和 Illingworth 于 1986 年发布在 Pattern Recognition 上的一篇论文。该论文假设原始图像中待分割的目标和背景的分布服从高斯分布&#xff0c;然后根据最小误差思想构建最小误差目标函数&#xff0c;最后取目标函数最…

JAVAEE初阶 网络编程(三)

TCP回显服务器 一. TCP的API二. TCP回显服务器的代码分析三. TCP回显服务器代码中存在的问题四. TCP回显服务器代码五. TCP客户端的代码六.TCP为基准的回显服务器的执行流程 一. TCP的API 二. TCP回显服务器的代码分析 这的clientSocket并不是表示用户端的层面东西&#xff0c;…

kubernets集群搭建

集群搭建 1.准备工作(所有节点都执行)1.1配置/etc/hosts文件1.2关闭防火墙1.3关闭selinux1.4关闭交换分区&#xff0c;提升性能1.5修改机器内核参数1.6配置时间同步1.7配置阿里云镜像源 2.安装docker服务(所有节点都执行)2.1安装docker服务2.2配置docker镜像加速和驱动 3.安装配…

【分布式技术】消息队列Kafka

目录 一、Kafka概述 二、消息队列Kafka的好处 三、消息队列Kafka的两种模式 四、Kafka 1、Kafka 定义 2、Kafka 简介 3、Kafka 的特性 五、Kafka的系统架构 六、实操部署Kafka集群 步骤一&#xff1a;在每一个zookeeper节点上完成kafka部署 ​编辑 步骤二&#xff1a…

【GitHub项目推荐--微软开源的课程(Web开发课程/机器学习课程/物联网课程/数据科学课程)】【转载】

微软在 GitHub 开源了四大课程&#xff0c;面向计算机专业或者入门编程的同学。分别是 Web 开发课程、机器学习课程、物联网课程和数据分析课程。 四大课程在 GitHub 上共斩获 90K 的Star&#xff0c;每一课程包含 20 多小节&#xff0c;完成课程大约需要 12 周。每小节除了视…

如何解决Xshell 连接不上虚拟机Ubuntu?

一、 在终端输入 sudo apt-get install openssh-server 二、 执行如下命令 sudo apt-get install ssh 三、 开启 ssh-server&#xff0c;输入密码 service ssh start 四、 验证&#xff0c;输入 ps -e|grep ssh&#xff0c;看到sshd成功 ps -e|grep ssh五、 连接

【Linux编辑器-vim使用】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、vim的基本概念 二、vim的基本操作 分屏操作&#xff1a; 三、vim正常&#xff08;命令&#xff09;模式命令集 四、vim末行&#xff08;底行&#xff09;模…

【经验分享】MAC系统安装R和Rstudio(保姆级教程)安装下载只需5min

最近换了Macbook的Air电脑&#xff0c;自然要换很多新软件啦&#xff0c;首先需要安装的就是R和Rstudio啦&#xff0c;网上的教程很多很繁琐&#xff0c;为此我特意总结了最简单实用的安装方式: 一、先R后Rstudio 二、R下载 下载网址&#xff1a;https://cran.r-project.org …

shell脚本基础演练

简介 Shell脚本是一种用于自动化执行一系列命令的脚本语言。在Unix和类Unix系统中&#xff0c;常见的Shell包括Bash、Zsh、Sh等。下面我将简要讲解Shell脚本的基本结构和一些常用写法&#xff0c;并附上一些标准的例子。 基础示例 基本结构 #!/bin/bash # 注释: 这是一个简…

什么是ORM思想?

1. ORM概念 ORM&#xff08;Object Relational Mapping&#xff09;对象关系映射模式&#xff0c;是一种技术&#xff0c;解决了面向对象与关系型数据库存互不匹配的现象。 ORM在业务逻辑层和数据库层之间充当了桥梁的作用。 2. ORM由来 在软件开发的过程中&#xff0c;通常…

力扣279. 完全平方数

动态规划 思路&#xff1a; 假设 dp[i] 为最少组成数 i 的平方数个数&#xff1b;则其上一个状态为 dp[i - j^2] 1&#xff0c;1 为 j^2&#xff1a; 即 i 的最少完全平方数 i - j^2 的最少完全平方数 1&#xff0c;其中 j^2 < i 为最接近 i 的平方数&#xff1b;初始值…

云计算管理-linux

1.权限 基本权限与归属 访问权限 读取&#xff1a;允许查看内容-read r 写入&#xff1a;允许修改内容-write w 可执行&#xff1a;允许运行和切换-excute x 对于文本文件&#xff1a; r读取权限&#xff1a;cat、less、grep、head、tail w写入权…

【BIAI】Lecture 6 - Somatosensory systems

Lecture 6- Somatosensory systems 专业术语 somatosensory system 体感系统 Thermoreceptors 温度感受器 Photoreceptors 光感受器 Chemoreceptoprs 化学感受器 hairy skin 毛发皮肤 glabrous skin 光滑皮肤 sensory receptors 感觉受体 dermal 真皮的 epidermal 表皮的 axon…

PSIM仿真DSP28335ADC功能并使用SCI串口模块输出曲线

在使用PSIM 2022 软件仿真DSP28335单片机时&#xff0c;发现里面还有SCI串口打印模块&#xff0c;在仿真软件里面可以看到串口数据&#xff0c;但是将代码下载到单片机上之后&#xff0c;使用串口助手却看不到任何数据&#xff0c;经过一番探索终于发现&#xff0c;串口不是这样…

C语言或C++通过IShellLinkA创建或解析lnk快捷方式(使用char字符数组)

本例程用到的COM接口有IShellLinkA和IPersistFile。 请注意因为函数参数的类型不为BSTR&#xff0c;所以这两个接口可直接传char *或wchar_t *字符串&#xff0c;不需要提前转化为BSTR类型。 C语言的写法&#xff1a; /* 这个程序只能在C编译器下编译成功, 请确保源文件的扩展…

Linux基本常用命令大全(一)

一、基本命令 1.1 关机和重启 关机 shutdown -h now 立刻关机 shutdown -h 5 5分钟后关机 poweroff 立刻关机 重启 shutdown -r now 立刻重启 shutdown -r 5 5分钟后重启 reboot 立刻重启 1.2 帮助命令 –help命令 shutdown --help&#xff1a; ifconfig --help&#xff1a…