代码随想录训练营第二十三天| 572.另一颗树的子树 104.二叉树的最大深度 559.N叉树的最大深度 111.二叉树的最小深度

572.另一颗树的子树:

状态:已做出

 思路:

这道题目当时第一时间不是想到利用100.相同的树思路来解决,而是先想到了使用kmp,不过这个题目官方题解确实是有kmp解法的,我使用的暴力解法,kmp的大致思路是使用前序遍历整个树的节点,并且要把所有的空子树都考虑进去,不然会出现前序相同树的结构不同的情况,这些节点都放入一个char型数组中,空节点可以任意使用一个字符来表示,做到这一步后就完全是把题目转变为了kmp问题,使用kmp来解决既可,暴力解法的思路:使用和100.相同的树相似的做法,遍历root的每个节点,把每个节点都看成一颗子树,然后这个子树和subRoot使用和100题相同的做法,查看两个树是否相同就能判断出最后的结果了。总体来说暴力解法的时间复杂度是O(n*m),而kmp的时间复杂度优化到O(n+m),n和m分别是root和subRoot的节点树。
代码如下:

/*** 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://两颗树进行比较是否相同bool dfs(TreeNode* root,TreeNode* sub) {if(!root && !sub) return true;if(!root || !sub ||(root->val!=sub->val)) return false;//这里的if语句把三种不相等的情况都包含进去了bool a1=dfs(root->left,sub->left);bool a2=dfs(root->right,sub->right);return a1 && a2;//需要左右子树都为真才说明这两个树相同}//这个函数是用来遍历树的每个节点的,让每个子树都和subRoot判断bool Subreturn(TreeNode* left, TreeNode* right) {bool rusult=dfs(left,right);if(rusult) return true;if(left==nullptr) return false;bool a1=Subreturn(left->left,right);bool a2=Subreturn(left->right,right);return a1 || a2;//使用递归来遍历所有root的节点,最后只要有一处子树和sunRoot相同就符合题意}bool isSubtree(TreeNode* root, TreeNode* subRoot) {if(!root) return false;return Subreturn(root,subRoot);}
};

遇到的困难:

当时做这道题目一开始以为使用100题的思路是优解,所以没想过暴解,就一直在想使用这个思路怎能去优化解决题目,但是发现一直出现问题,因为这道题要优化时间的话必须要考虑判断出错后怎么去回溯,这就让我想到了kmp,随后看完官方的解法后才知道这到题目使用判断相同数的思路就是暴力解法,必须要每个节点都判断才能得到正确答案,官方题解还给出了一种使用哈希树的解法,听着就你难,所以完全看思路。

收获:

这道题目使用判断是否是相同的数的方法就是暴力,通过练习熟悉一下这种解法,做法和之前的100题几乎一样,这道题目跟字符串求是否有相同子串的思想很像。

104.二叉树的最大深度:

文档讲解:代码随想录|104.二叉树的最大深度

视频讲解:二叉树的高度和深度有啥区别?究竟用什么遍历顺序?很多录友搞不懂 | LeetCode:104.二叉树的最大深度_哔哩哔哩_bilibili

状态:已做出

思路:

这下题目之前我使用层序遍历解决过,这次主要是使用前序和后续来解决这代题目。后序的思路:使用后续就是求根结点的最大高度,我的递归结束条件是节点为空时返回0,每次递归设置两个变量,分别保存这个节点的左右子树的层数有多少,最后去这两者的最大值,最后返回最大值加一,按照这个递归思路打到根结点就能返回最大深度。前序思路:前序是求最深的叶子结点深度。和后序递归不同,递归代码的参数我多设计了一个变量n,用来记录此时的层级,在递归到节点为空后返回n结束递归,每层设置两个变量来保存次节点的左右子树的最大深度,然后去这两个变量的最大值,直接返回最大值就可以了。

后序遍历:

/*** 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 dfs(TreeNode* root) {if(root==nullptr) {return 0;//这里返回零是为了从最深的地方开始不断向上回溯来记录高度}int sum1=dfs(root->left);int sum2=dfs(root->right);int n=max(sum1,sum2);//去最大值return ++n;//这里需要把此时的节点考虑进去,所以要加一}int maxDepth(TreeNode* root) {if(!root) return 0;return dfs(root);}
};

前序遍历:

/*** 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 dfs(TreeNode* root,int n) {if(root==nullptr) {return n;//返回n,因为这里空节点不考虑}int sum1=dfs(root->left,n+1);//每次都要让参数加一,记录层级int sum2=dfs(root->right,n+1);int num=max(sum1,sum2);return num;//这里之所以不加一是因为在遍历后序节点的时候num就已经把加一操作包含进去了,比如如果只有根节点的话,最后不加一也返回深度为1}int maxDepth(TreeNode* root) {if(!root) return 0;return dfs(root,0);}
};

遇到的困难:

这道题目使用前后序来做比层序遍历难一点,其中的难点就是难以控制递归的代码,不好记录层级,首先后序我使用递归返回0的方式是为了考虑最后节点为空的那一层,随后使用两个变量分别保存左右子树的最大深度,就是没一层每一层的递归来找到最后根结点的最大深度的,这个点就是是递归抽象的地方,需要由深到浅来思考,不然就会想错,最后返回的最大值我多加了1是为了把这一层考虑进去,因为左右子节点的最大高度都求出了,最后要加上这一次的层级返回。前序递归结束返回n是因为我在每层都讲n累加了,所以直接返回n就行了,下面的两个变量的递归传入n+1就是累加层级,最后和后序一样返回最大值,这里不和后序一样返回最大值加一是因为在左右子树递归后判断的最大值就已经把这一层级考虑进去了,所以直接返回。

收获:

这道题目使用层序遍历比递归方法要简单,主要是层序好理解,递归还是有点抽象,这道题对加深递归理想有一定的帮助,相比前中后序的简单递归,这道题目需要更加了解递归的规则才能合理分配出层级或者高度的改变。

559.N叉树的最大深度 :

文档讲解:代码随想录|104.二叉树的最大深度

状态:已做出 

思路:

这道题目和上一道求二叉树最大深度一样,我使用了前序后序和层序三种遍历方式去实现了这道题目。这里后序实现最后结束递归是返回的1,因为这里二叉树后序不一样,二叉树可以递归到空节点,但是N叉树不能,所以这里返回后必须要把这一层考虑进去,所以返回放是1,随后的操作二叉树的就差不多了,就是要使用循环来一直遍历一个节点的所有节点,每次循环记比较大小,保存这些节点的最大值,最后好和二叉树思想一样,返回最大值加一。前序则和二叉树放最大深度求法没太大的区别,直接改成循环遍历所有直接点既可。层序遍历相比于递归就简单多了,层序遍历所有节点,记录每层层级最后返回就可以了。

后序遍历:

/*
// Definition for a Node.
class Node {
public:int val;vector<Node*> children;Node() {}Node(int _val) {val = _val;}Node(int _val, vector<Node*> _children) {val = _val;children = _children;}
};
*/class Solution {
public:int dfs(Node* root) {if(!root->children.size()) return 1;//这里是返回1,因为最后是遇到叶子节点才结束递归,要算上叶子节点int ans=0;//这里和而二叉树不同,需要循环遍历所有子节点。其他和二叉树的思路差不多for(int i=0;i<root->children.size();++i) {int sum=dfs(root->children[i]);ans=max(sum,ans);}return ans+1;//算上此节点层级}int maxDepth(Node* root) {if(!root) return 0;return dfs(root);}
};

前序遍历:

/*
// Definition for a Node.
class Node {
public:int val;vector<Node*> children;Node() {}Node(int _val) {val = _val;}Node(int _val, vector<Node*> _children) {val = _val;children = _children;}
};
*/class Solution {
public:int dfs(Node* root,int n) {if(!root->children.size()) return n;//这里在递归参数就考虑到了加一的情况,所以直接返回nint ans=0;for(int i=0;i<root->children.size();++i) {int sum=dfs(root->children[i],n+1);ans=max(sum,ans);}return ans;}int maxDepth(Node* root) {if(!root) return 0;return dfs(root,1);}
};

层序遍历:

/*
// Definition for a Node.
class Node {
public:int val;vector<Node*> children;Node() {}Node(int _val) {val = _val;}Node(int _val, vector<Node*> _children) {val = _val;children = _children;}
};
*/class Solution {
public:int maxDepth(Node* root) {if(!root) return 0;queue<Node*>qu;qu.push(root);int n=0;while(!qu.empty()) {int size=qu.size();++n;//每一层都要加上层级for(int i=0;i<size;++i) {Node* temp=qu.front();qu.pop();for(int j=0;j<temp->children.size();++j) {qu.push(temp->children[j]);}}}return n;}
};

遇到的困难:

这道题目难点就是N叉树有多个节点,需要在递归和层序遍历里面设置一个循环来遍历所有结点,还有一点就是N叉树因为不会递归到空节点,所以后序需要对代码进行一点细节的改善。

收获:

这道题目就是二叉树的进阶,和二叉树的求法没太大区别,练习能进一步理解二叉树的代码思路。

 111.二叉树的最小深度:

文档讲解:代码随想录|111.二叉树的最小深度

视频讲解:看起来好像做过,一写就错! | LeetCode:111.二叉树的最小深度_哔哩哔哩_bilibili

状态:已做出

思路:

这道题目使用层序我之前做过,这次主要是使用前序和后序的递归来实现,这道题目我觉得使用递归实现起来比求最大深度还要麻烦一点,这里容易出错的问题文档中有明确说明,就是不明确处理叶子结点就会出现误判,比如根结点的左子树为空时,不管右子树是否为空最后出现的最小深度都是1。这道题的具体要求是要我们求根结点到最浅层级的深度有多大,所以递归的结束条件我这里设置的是到叶子节点后结束递归,后序为了考虑这一层所以返回1,前序我这里在递归里设置了一个参数n来记录层级,和二叉树的思路有点点相似,每到一层就n+1。不管是后序还是前序都先设置两个变量,并让变量指向int最大值,因为每次都需要比较取最小值,而且每次递归都要判断此节点做右子树必须是非空才能进行递归,这样是为了不出现考虑空节点层级的情况。
代码如下:

后序遍历:

/*** 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 dfs(TreeNode* root) {if(!root->left && !root->right) return 1;int sum1=INT_MAX,sum2=INT_MAX;//这里先设置两个变量为最大值,因为下面的递归困难会因为子节点为空而不会改变变量的值//这里是为了避免文档所说的错误,所以设置了if语句if(root->left)sum1=dfs(root->left);if(root->right)sum2=dfs(root->right);return min(sum1,sum2)+1;}int minDepth(TreeNode* root) {if(!root) return 0;return dfs(root);}
};

前序遍历:

/*** 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 dfs(TreeNode* root,int n) {if(!root->left && !root->right) return n;//叶子节点就直接返回结束递归int sum1=INT_MAX,sum2=INT_MAX;if(root->left)sum1=dfs(root->left,n+1);if(root->right)sum2=dfs(root->right,n+1);return min(sum1,sum2);}int minDepth(TreeNode* root) {if(!root) return 0;return dfs(root,1);//这里设置为1是直接先把根节点考虑进去了}
};

遇到的困难:

使用层序遍历求最小比求最大要简单,没想到使用递归却相反,求最小反而细节处更多。

收获:

以上这些题目主要都是使用递归去实现的,主要是提升对递归的掌握成程度。

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

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

相关文章

【RabbitMq C++】消息队列组件

RabbitMq 消息队列组件 1. RabbitMq介绍2. 安装RabbitMQ3. 安装 RabbitMQ 的 C客户端库4. AMQP-CPP 库的简单使用4.1 使用4.1.1 TCP 模式4.1.2 扩展模式 4.2 常用类与接口介绍4.2.1 Channel4.3.2 ev 5. RabbitMQ样例编写5.1 发布消息5.2 订阅消息 1. RabbitMq介绍 RabbitMq - …

鸿蒙NEXT开发动画案例8

1.创建空白项目 2.Page文件夹下面新建Spin.ets文件&#xff0c;代码如下&#xff1a; /*** SpinKit动画组件 (重构版)* author: CSDN-鸿蒙布道师* since: 2025/05/14*/interface AnimationGroup {indexes: number[];delay: number; }ComponentV2 export struct SpinEight {Re…

MySQL全局优化

目录 1 硬件层面优化 1.1 CPU优化 1.2 内存优化 1.3 存储优化 1.4 网络优化 2 系统配置优化 2.1 操作系统配置 2.2 MySQL服务配置 3 库表结构优化 4 SQL及索引优化 mysql可以从四个层面考虑优化&#xff0c;分别是 硬件系统配置库表结构SQL及索引 从成本和优化效果来看&#xf…

vue和springboot交互数据,使用axios【跨域问题】

vue和springboot交互数据&#xff0c;使用axios【跨域问题】 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是node.js和vue的使用。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性。【帮帮志系列文章】&…

FFMPEG 与 mp4

1. FFmpeg 中的 start_time 与 time_base start_time 流的起始时间戳&#xff08;单位&#xff1a;time_base&#xff09;&#xff0c;表示第一帧的呈现时间&#xff08;Presentation Time&#xff09;。通常用于同步多个流&#xff08;如音频和视频&#xff09;。 time_base …

AI世界的崩塌:当人类思考枯竭引发数据生态链断裂

AI世界的崩塌&#xff1a;当人类思考枯竭引发数据生态链断裂 ——论过度依赖AI创作对技术进化的反噬 一、数据生态的恶性循环&#xff1a;AI的“自噬危机” 当前AI模型的训练依赖于人类创造的原始数据——书籍、论文、艺术作品、社交媒体动态等。据统计&#xff0c;2025年全球…

C++【STL】(2)string

C【STL】string用法扩展 1. assign&#xff1a;为字符串赋新值 用于替换字符串内容&#xff0c;支持多种参数形式。 常用形式&#xff1a; // 用另一个字符串赋值 str.assign("Hello World");// 用另一个字符串的子串&#xff08;从第6个字符开始&#xff0c;取5…

树莓派4基于Debian GNU/Linux 12 (Bookworm)开启VNC,使用MobaXterm连接VNC出现黑屏/灰屏问题

1. 开启树莓派的VNC服务 启用VNC服务&#xff1a;通过raspi-config开启 # 1. 通过 raspi-config 工具开启 sudo raspi-config选择 Interface Options → VNC → Yes退出时会自动启动服务 检查服务状态&#xff1a; sudo systemctl status vncserver-x11-serviced正常输出应显示…

MongoDB使用x.509证书认证

文章目录 自定义证书生成CA证书生成服务器之间的证书生成集群证书生成用户证书 MongoDB配置java使用x.509证书连接MongoDBMongoShell使用证书连接 8.0版本的mongodb开启复制集&#xff0c;配置证书认证 自定义证书 生成CA证书 生成ca私钥&#xff1a; openssl genrsa -out ca…

Python爬虫实战:研究js混淆加密

一、引言 在当今数字化时代,数据已成为推动各行业发展的核心驱动力。网络爬虫作为一种高效的数据采集工具,能够从互联网上自动获取大量有价值的信息。然而,随着互联网技术的不断发展,许多网站为了保护自身数据安全和知识产权,采用了 JavaScript 混淆加密技术来防止数据被…

Java项目层级介绍 java 层级 层次

java 层级 层次 实体层 控制器层 数据连接层 Service : 业务处理类 Repository &#xff1a;数据库访问类 Java项目层级介绍 https://blog.csdn.net/m0_67574906/article/details/145811846 在Java项目中&#xff0c;层级结构&#xff08;Layered Architecture&#xf…

网络安全顶会——SP 2025 论文清单与摘要

1、"Check-Before-you-Solve": Verifiable Time-lock Puzzles 时间锁谜题是一种密码学原语&#xff0c;它向生成者保证该谜题无法在少于T个顺序计算步骤内被破解。近年来&#xff0c;该技术已在公平合约签署和密封投标拍卖等场景中得到广泛应用。然而&#xff0c;求解…

《100天精通Python——基础篇 2025 第18天:正则表达式入门实战,解锁字符串处理的魔法力量》

目录 一、认识正则表达式二、正则表达式基本语法2.1 行界定符2.2 单词定界符2.3 字符类2.4 选择符2.5 范围符2.6 排除符2.7 限定符2.8 任意字符2.9 转义字符2.10 反斜杠2.11 小括号2.11.1 定义独立单元2.11.2 分组 2.12 反向引用2.13 特殊构造2.14 匹配模式 三、re模块3.1 comp…

思迈特软件携手天阳科技,打造ChatBI金融智能分析新标杆

5月10日&#xff0c;广州思迈特软件有限公司&#xff08;以下简称“思迈特软件”&#xff09;与天阳宏业科技股份有限公司&#xff08;以下简称“天阳科技”&#xff09;在北京正式签署战略合作协议。思迈特软件董事长吴华夫、CEO姚诗成&#xff0c;天阳科技董事长兼总裁欧阳建…

OPENSSL-1.1.1的使用及注意事项

下载链接&#xff1a; OpenSSL1.1.1一个广泛使用的开源加密库资源-CSDN文库 OpenSSL 1.1.1 是一个广泛使用的开源加密库&#xff0c;以下是其使用方法及注意事项&#xff1a; 使用方法 安装&#xff1a; Linux系统&#xff1a; 从源码编译安装&#xff1a;访问 OpenSSL 官网…

数据库优化

一、慢 SQL 排查全流程 1. 开启慢查询日志&#xff1a;精准定位问题 SQL 慢查询日志是定位性能问题的首要工具&#xff0c;通过记录执行超时或未使用索引的 SQL&#xff0c;为优化提供依据。 配置步骤&#xff1a; ① 临时启用&#xff08;生效至服务重启&#xff09; sql …

GO语言-导入自定义包

文章目录 1. 项目目录结构2. 创建自定义包3. 初始化模块4. 导入自定义包5. 相对路径导入 在Go语言中导入自定义包需要遵循一定的目录结构和导入规则。以下是详细指南&#xff08;包含两种方式&#xff09;&#xff1a; 1. 项目目录结构 方法1&#xff1a;适用于Go 1.11 &#…

记录算法笔记(2025.5.11) 二叉树的中序遍历

给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; 输入&#xff1a;root [1] …

【iptables防火墙】 -- DDos防御

最近有客户要定制路由器的默认防火墙等级&#xff0c;然后涉及到了DDos规则&#xff0c;对比客户提供的规则发现我们现有的规则存在明显的错误&#xff0c;在此记录一下如何使用iptables防护DDoS攻击 直接贴一下规则 #开启TCP SYN Cookies 机制 sysctl -w net.ipv4.tcp_synco…

[Java][Leetcode simple]26. 删除有序数组中的重复项

思路 第一个元素不动从第二个元素开始&#xff1a;只要跟上一个元素不一样就放入数组中 public int removeDuplicates(int[] nums) {int cnt1;for(int i 1; i < nums.length; i) {if(nums[i] ! nums[i-1]) {nums[cnt] nums[i];}}return cnt;}