Leetcode算法训练日记 | day20
一、合并二叉树
1.题目
Leetcode:第 617 题
给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
示例 1:

输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7] 输出:[3,4,5,5,4,null,7]
示例 2:
输入:root1 = [1], root2 = [1,2] 输出:[2,2]
2.解题思路
首先检查两个输入树的根节点是否为空,如果其中一个为空,则返回另一个作为结果。如果两个根节点都不为空,将合并它们的值,并对它们的左右子树递归地执行合并操作。这个过程一直持续到所有节点都被合并,最终返回更新后的根节点,包含了合并后二叉树的根。
3.实现代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;// 定义一个结构体TreeNode,用于表示二叉树的节点。
struct TreeNode {int val; // 存储节点的值。TreeNode* left; // 指向该节点左子树的指针。TreeNode* right; // 指向该节点右子树的指针。// TreeNode的构造函数,用于创建一个TreeNode实例。// 参数x是节点的值,left和right默认为NULL,表示没有左右子节点。TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};// 一、合并两棵二叉树(递归法)。
class Solution1 {
public:// mergeTrees函数用于合并两个给定的二叉树root1和root2。TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {if (root1 == NULL) return root2;// 如果root1为空,则返回root2作为合并后的树的根节点。if (root2 == NULL) return root1; // 如果root2为空,则返回root1作为合并后的树的根节点。root1->val = root1->val + root2->val;// 将root1的值与root2的值相加,并将结果赋给root1,这是合并操作的一部分。root1->left = mergeTrees(root1->left, root2->left);// 递归调用mergeTrees函数合并root1和root2的左子树。root1->right = mergeTrees(root1->right, root2->right); // 递归调用mergeTrees函数合并root1和root2的右子树。return root1;// 返回更新后的root1作为合并后的树的根节点。}
};// 二、合并两棵二叉树(迭代法法)。
class Solution2 {
public:// mergeTrees函数用于合并两个给定的二叉树root1和root2。TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {if (root1 == NULL) return root2; // 如果root1为空,直接返回root2作为合并后的树的根节点。if (root2 == NULL) return root1; // 如果root2为空,直接返回root1作为合并后的树的根节点。queue<TreeNode*> que; // 创建一个队列que,用于在合并过程中存储待处理的节点对。que.push(root1); // 将root1和root2入队。que.push(root2);// 使用while循环处理队列中的所有节点对。while (!que.empty()) {// 取出队列中的两个节点,node1对应root1的节点,node2对应root2的节点。TreeNode* node1 = que.front();que.pop();TreeNode* node2 = que.front();que.pop();node1->val = node1->val + node2->val;// 将node1和node2的值相加,并将结果赋给node1。// 如果node1和node2都有左子节点,将它们入队以进行后续合并。if (node1->left != NULL && node2->left != NULL) {que.push(node1->left);que.push(node2->left);}// 如果node1和node2都有右子节点,将它们入队以进行后续合并。if (node1->right != NULL && node2->right != NULL) {que.push(node1->right);que.push(node2->right);}//因为返回的是root1二叉树,只需考虑考虑root1存在空节点对应的root2不为空节点的情况// 而不需要考虑root1存在节点对应的root2为空节点的情况// 如果node1没有左子节点,但node2有左子节点,将node2的左子节点赋给node1。if (node1->left == NULL && node2->left != NULL) {node1->left = node2->left;}// 如果node1没有右子节点,但node2有右子节点,将node2的右子节点赋给node1。if (node1->right == NULL && node2->right != NULL) {node1->right = node2->right;}//因为返回的是root1二叉树,所以不需要考虑root1存在节点对应的root2为空节点的情况}return root1;// 由于函数只接收root1的指针,返回root1,此时它已经是合并后的树的根节点。}
};
二、二叉搜索树中的搜索
1.题目
Leetcode:第 700 题
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。
示例 1:

输入:root = [4,2,7,1,3], val = 2 输出:[2,1,3]
示例 2:

输入:root = [4,2,7,1,3], val = 5 输出:[]
2.解题思路
首先检查当前根节点是否为空或者是否已经找到目标值。如果当前节点为空,或者其值等于目标值,则直接返回当前节点。如果当前节点的值大于目标值,函数递归地在左子树中查找;如果当前节点的值小于目标值,则递归地在右子树中查找。最终,函数返回查找结果,如果找到了匹配的节点,则返回该节点;否则返回NULL。
3.实现代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;// 定义一个结构体TreeNode,用于表示二叉树的节点。
struct TreeNode {int val; // 存储节点的值。TreeNode* left; // 指向该节点左子树的指针。TreeNode* right; // 指向该节点右子树的指针。// TreeNode的构造函数,用于创建一个TreeNode实例。// 参数x是节点的值,left和right默认为NULL,表示没有左右子节点。TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};// 一、在二叉搜索树中查找特定值的节点(递归法)。
class Solution1 {
public:// searchBST函数用于在二叉搜索树root中查找值为val的节点。TreeNode* searchBST(TreeNode* root, int val) {if (root == NULL || root->val == val) return root; // 如果根节点为空,或者根节点的值等于要查找的值val,返回当前节点。TreeNode* result = NULL;// 初始化结果指针为NULL,用于存储找到的节点。if (root->val > val) result = searchBST(root->left, val);// 如果根节点的值大于要查找的值val,递归搜索左子树。if (root->val < val) result = searchBST(root->right, val);// 如果根节点的值小于要查找的值val,递归搜索右子树。 return result;// 返回搜索结果,如果找到则返回找到的节点,否则返回NULL。}
};// 二、在二叉搜索树中查找特定值的节点(递归法)。
class Solution2 {
public:// searchBST函数用于在二叉搜索树root中查找值为val的节点并返回。TreeNode* searchBST(TreeNode* root, int val) {while (root != NULL) { // 使用while循环,当root不为NULL时继续搜索。if (root->val > val) {// 如果root的值大于要查找的值val,向左子树搜索。root = root->left;}else if (root->val < val) {// 如果root的值小于要查找的值val,向右子树搜索。root = root->right;}else {// 如果root的值等于要查找的值val,找到了目标节点,返回root。return root;}}return NULL; //未找到就返回NULL。}
};
三、验证二叉搜索树
1.题目
Leetcode:第 98 题
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左
子树
只包含 小于 当前节点的数。 - 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:

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

输入:root = [5,1,4,null,null,3,6] 输出:false 解释:根节点的值是 5 ,但是右子节点的值是 4 。
2.解题思路
1.一般递归法:递归遍历整个二叉树,将所有节点的元素使用vector保存,检查是否所有的元素都是严格递增的,如果不是,就说明不是一个有效的二叉搜索树。
2.双指针递归法:在递归遍历整个二叉树的过程中,用两个指针来检查是否满足每个节点的值都应该大于其左子树中所有节点的值,并且小于其右子树中所有节点的值。如果不是,就说明不是一个有效的二叉搜索树。
3.迭代法:通过使用栈 st 来存储待访问的节点,可以在每次循环中选择最左边的节点进行访问,从而模拟中序遍历的过程。同时,使用指针 pre 来记录遍历过程中的前一个节点值,以便在访问当前节点时检查其是否违反了二叉搜索树的性质。如果遍历完整棵树都没有发现违反性质的情况,则可以认为该二叉树是有效的二叉搜索树。
3.实现代码
#include <iostream>
#include <vector>
#include <stack>
using namespace std;// 定义一个结构体TreeNode,用于表示二叉树的节点。
struct TreeNode {int val; // 存储节点的值。TreeNode* left; // 指向该节点左子树的指针。TreeNode* right; // 指向该节点右子树的指针。// TreeNode的构造函数,用于创建一个TreeNode实例。// 参数x是节点的值,left和right默认为NULL,表示没有左右子节点。TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};// 一、验证二叉搜索树(一般递归法)。
class Solution {
public:vector<int> vec; // 定义一个vec,用于存储二叉树节点的值// 定义一个名为traversal的成员函数,用于执行二叉树的中序遍历。void traversal(TreeNode* root) {if (root == NULL) return; // 如果当前节点为空,直接返回,不执行任何操作。traversal(root->left); // 递归调用traversal函数遍历当前节点的左子树。vec.push_back(root->val); // 访问当前节点,将其值添加到vec中。traversal(root->right); // 递归调用traversal函数遍历当前节点的右子树。}// 定义一个名为isValidBST的成员函数,用于验证给定的二叉树是否为有效的二叉搜索树。// 参数root是二叉树的根节点指针。bool isValidBST(TreeNode* root) {vec.clear(); // 清空向量vec,为新的中序遍历做准备。traversal(root); // 调用traversal函数,传入根节点,执行中序遍历。for (int i = 1; i < vec.size(); i++) {// 遍历向量vec,检查中序遍历的结果是否为升序。if (vec[i] <= vec[i - 1]) return false; // 如果发现任何违反升序的元素对,返回false。}return true; // 如果遍历完成没有发现违反升序的元素对,返回true,表明是有效的二叉搜索树。}
};//二、验证二叉搜索树(双指针递归法)。
class Solution2 {
public:// 定义一个指向TreeNode的指针pre,初始化为NULL,用于在遍历过程中记录前一个访问的节点。TreeNode* pre = NULL;// 定义一个名为isValidBST的成员函数,用于验证给定的二叉树是否为有效的二叉搜索树。// 参数root是二叉树的根节点指针。bool isValidBST(TreeNode* root) {if (root == NULL) return true; // 如果当前节点为空,说明是有效的二叉搜索树,返回true。// 递归调用isValidBST函数检查当前节点的左子树是否为有效的二叉搜索树。bool left = isValidBST(root->left);// 如果pre不为NULL,并且前一个访问的节点的值大于当前节点的值,说明不是有效的二叉搜索树,返回false。// 这是二叉搜索树的性质:每个节点的值都应该大于其左子树中所有节点的值。if (pre != NULL && pre->val > root->val) return false;pre = root; // 更新pre为当前节点,以便在递归检查右子树时使用。// 递归调用isValidBST函数检查当前节点的右子树是否为有效的二叉搜索树。bool right = isValidBST(root->right);// 返回左子树和右子树的检查结果,只有当左右子树都满足二叉搜索树的性质时,整个树才是有效的。return left && right;}
};// 三、验证二叉搜索树(迭代法)。
class Solution3 {
public:// 定义一个成员函数isValidBST,用于验证给定的二叉树是否为有效的二叉搜索树。// 参数root是二叉树的根节点指针。bool isValidBST(TreeNode* root) {stack<TreeNode*> st; // 定义一个栈st,用于存放二叉树的节点指针,辅助进行迭代遍历。TreeNode* cur = root; // 定义一个当前节点指针cur,初始指向根节点。TreeNode* pre = NULL; // 定义一个前一个节点指针pre,初始为NULL,用于记录遍历过程中的前一个节点值。// 当当前节点不为空,或者栈st不为空时,继续遍历。while (cur != NULL || !st.empty()) {if (cur != NULL) {// 如果当前节点不为空,将当前节点压入栈st,并将cur更新为当前节点的左子节点。st.push(cur); // 将当前节点压入栈中。cur = cur->left; // 将cur更新为当前节点的左子节点,开始遍历左子树。}else {// 如果当前节点为空,从栈st中弹出一个节点作为当前节点。cur = st.top(); // 获取栈顶节点。st.pop(); // 弹出栈顶节点。// 如果pre不为空,并且当前节点的值小于pre记录的前一个节点的值,说明不是有效的二叉搜索树,返回false。// 这是二叉搜索树的性质:每个节点的值都应该大于其左子树中所有节点的值。if (pre != NULL && cur->val <= pre->val) {return false;}pre = cur;// 更新pre为当前节点。cur = cur->right;// 将cur更新为当前节点的右子节点,准备遍历右子树。}}// 如果遍历完整棵树都没有发现违反二叉搜索树性质的情况,则返回true,表明是有效的二叉搜索树。return true;}
};
ps:以上皆是本人在探索算法旅途中的浅薄见解,诚挚地希望得到各位的宝贵意见与悉心指导,若有不足或谬误之处,还请多多指教。
相关文章:
Leetcode算法训练日记 | day20
一、合并二叉树 1.题目 Leetcode:第 617 题 给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新…...
conda创建虚拟环境太慢,Collecting package metadata (current_repodata.json): failed
(省流版:只看加粗红色,末尾也有哦) 平时不怎么用conda,在前公司用服务器的时候用的是公司的conda源,在自己电脑上直接用python创建虚拟环境完事儿,所以对conda的配置并不熟悉~~【狗头】。但是python虚拟环境的最大缺点…...
Tensorflow(GPU版本配置)一步到位!!!
Tensorflow(GPU版本配置)一步到位!!! CUDA安装CUDA配置Tensorflow配置常见的包 CUDA安装 配置了N次的Tensorflow–Gpu版本,完成了踩坑,这里以配置Tensorflow_gpu 2.6.0为例子进行安装 以下为ten…...
STL之map
CSTL之map 1.介绍 map是映射的意思,即每个x对应一个y,我们这里说成key和value 举例子说明:运动->篮球 (运动是key,篮球是value)用电脑->写代码 (用电脑是key,写代码是value)…...
闲谈2024(一)
时光飞逝,一转眼24年的第一个季度已经过去了,回望这3个多月,感触颇多。首先,24年从一个一心只读圣贤书,全身心投入在技术上的研发工程师,转变为一个团队的小leader。从我个人对自己的定位来说,我…...
SQL注入利用 学习- 布尔盲注
布尔盲注适用场景: 1、WAF或者过滤函数完全过滤掉union关键字 2、页面中不再回显具体数据,但是在SQL语句执行成功或失败返回不同的内容 代码分析:过滤关键字 union if(preg_match(/union/i, $id)) { echo "fail"; exit; } 代码…...
前端项目部署教程——有域名有证书
一、拉取nginx镜像 docker pull nginx //先拉取nginx镜像二、打包前端项目 1、将Vue打包项目传输到/usr/local/vue/下blog和admin文件夹下 重点: 每一个子域名都要申请证书,在阿里云每年可以免费申请20个证书, 免费证书申请教程在 免费证书申请教程 …...
《看漫画学C++》第12章 可大可小的“容器”——向量
在C编程的世界里,数组是一种基础且广泛使用的数据结构。然而,传统的静态数组在大小固定、管理不便等方面的局限性,常常让开发者感到束手束脚。幸运的是,C标准库中的vector类为我们提供了一种更加灵活、高效的动态数组解决方案。 …...
OpenAI推出GPTBot网络爬虫:提升AI模型同时引发道德法律争议
文章目录 一、GPTBot 简介二、功能特点三、技术细节3.1、用户代理标识3.2、数据采集规则3.3、数据使用目的3.4、网站屏蔽方法3.5、数据过滤 四、GPTBot 的道德和法律问题五、GPTBot 的使用方法和限制六、总结 一、GPTBot 简介 OpenAI 推出的网络爬虫GPTBot旨在通过从互联网上收…...
Claude使用教程
claude 3 opus面世后,网上盛传吊打了GPT-4。网上这几天也已经有了许多应用,但竟然还有很多小伙伴不知道国内怎么用gpt,也不知道怎么去用这个据说已经吊打了gpt-4的claude3。 今天我们想要进行的一项尝试就是—— 用claude3和gpt4,…...
【经典算法】LeetCode25:K 个一组翻转链表(Java/C/Python3,Hard)
#算法 目录 题目描述思路及实现方式一:递归思路代码实现Java 版本C 语言版本Python3 版本 复杂度分析 方式二:迭代和原地反转思路代码实现Java 版本C 语言版本Python3 版本 复杂度分析 总结相似题目 标签:链表、递归 题目描述 给你链表的头…...
6.11物联网RK3399项目开发实录-驱动开发之定时器的使用(wulianjishu666)
嵌入式实战开发例程【珍贵收藏,开发必备】: 链接:https://pan.baidu.com/s/1tkDBNH9R3iAaHOG1Zj9q1Q?pwdt41u 定时器使用 前言 RK3399有 12 个 Timers (timer0-timer11),有 12 个 Secure Timers(stimer0~stimer11) 和 2 个 …...
算法训练营第二十三天(二叉树完结)
算法训练营第二十三天(二叉树完结) 669. 修剪二叉搜索树 力扣题目链接(opens new window) 题目 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>L) 。你可能需要改…...
mysql主从复制Slave_SQL_Running: No
1、SHOW SLAVE STATUS \G; Slave_SQL_Running: No 解决方案: 重新同步主库和从库的数据 1、从库先停掉slave stop slave; 2、在主库查看此时的日志文件和位置 show master status; 3、在从库中执行 change master to master_host192.168.2.177,master_userslave…...
【SpringBoot】SpringBoot项目快速搭建
本文将介绍Springboot项目的快速搭建 快速创建SpringBoot项目 打开IDEA在File->New->Project中新建项目 点击左侧的Spring Initializr 输入以下信息: Name 项目名称Group 根据公司域名来,或者默认com.example【倒序域名】Package Name 包名&am…...
Terraform 状态不同步处理
背景 在使用 Terraform 创建 TencentCloud TKE 的时候,手贱把 node pool 删掉了。导致执行 destroy, plan 都会报错。 │ Error: [TencentCloudSDKError] CodeInternalError.UnexpectedInternal, Messagerelated node pool query err(get node pool failed: [E501…...
4.2.k8s的pod-标签管理、镜像拉取策略、容器重启策略、资源限制、优雅终止
一、标签管理 1.标签在k8s中极其重要,大多数资源的相互关联就需要使用标签;也就是说,资源的相互关联大多数时候,是使用标签进行关联的; 2.其他作用,在k8s集群中,node节点的一些操作比如污点及污…...
能源党建后台项目总结
1.引入 本次框架是Ruoyi-plusvue2element组合。 2.样式 由于是后台项目,样式要求统一,不可以有的输入框长有的短。着重几点: 1.关于form表单应该如何水平布局 在element中,form有个属性叫::inline"true"…...
股票高胜率的交易法则是什么?
股票交易中的高胜率交易法则并非一成不变,而是根据市场状况、个人投资风格和经验等多种因素综合而定的。以下是一些有助于提升交易胜率的法则和策略: 1.趋势跟踪法则:在股票交易中,趋势跟踪是一种有效的策略。通过观察大盘和个股…...
C语言 | sizeof与strlen的区别(附笔试题)
目录: 1. sizeof和strlen的对比 2. 数组和指针 笔试题解析 3. 指针运算 笔试题解析 内容多多,需耐心看完,加油!!! 一.sizeof和strlen的对比 1.1 sizeof 在学习操作符的时候,我们学习了 s…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
