Day 20 654.最大二叉树 617.合并二叉树 700.二叉搜索树中的搜索 98.验证二叉搜索树

最大二叉树

给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:

  • 二叉树的根是数组中的最大元素。
  • 左子树是通过数组中最大值左边部分构造出的最大二叉树。
  • 右子树是通过数组中最大值右边部分构造出的最大二叉树。

通过给定的数组构建最大二叉树,并且输出这个树的根节点。

示例 :

654.最大二叉树

1 <= nums.length <= 1000

0 <= nums[i] <= 1000

nums 中的所有整数 互不相同

​ 构造过程如下:

​ 构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树;

​ 遍历第一步,确定函数参数和返回值:

​ 参数传入的是存放元素的数组,返回该数组构造的二叉树的头结点,返回类型是指向节点的指针:

TreeNode* constructMaximumBinaryTree(vector<int>& nums)

​ 遍历第二步:

​ 确定终止条件,由于本题要求是用数组构建,且题目给出数组的长度大于等于一,所以不用考虑数组非空的情况;

​ 当数组长度为一时,说明此时遍历到了叶子节点,此时定义新节点并返回节点;

TreeNode* node = new TreeNode(0);
if (nums.size() == 1) {node->val = nums[0];return node;
}

​ 遍历第三步:

​ 确定单层遍历条件:
​ 由于需要数组最大值作为根节点,所以优先遍历整个数组获取最大值作为根节点,并得到这个最大值的下标作为分割边界;思路可以参考之前刚做过的中序后序构建二叉树一致,可以用新数组vector,也可以直接传入函数时定义两个int型变量记录左右区间,这里保持函数定义一致以vector型为例,若考虑代码性能选择后者;

	int MaxValue = 0;//获得数组最大值,由于题目给出条件数组为非负自然数,所以此处无须定义为INT_MINint Index = 0;//定义最大值下标for(int i = 0; i < right - left/*nums.size()*/; i++){//遍历完毕,获得最大值if(nums[i] > MaxValue){MaxValue = nums[i];Index = i;}}TreeNode* node = new TreeNode(0);node->val = MaxValue;/*上述代码为"中"的处理过程*/if(Index > 0){//左子树不为空vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);node->left = constructMaximumBinaryTree(newVec);}if(nums.size()- Index - 1 > 0){//右子树不为空vector<int> newVec(nums.begin() + maxValueIndex + 1, nums.end());node->right = constructMaximumBinaryTree(newVec);}

​ 整体代码如下:

class Solution {
public:TreeNode* constructMaximumBinaryTree(vector<int>& nums) {TreeNode* node = new TreeNode(0);if (nums.size() == 1) {node->val = nums[0];return node;}// 找到数组中最大的值和对应的下标int maxValue = 0;int maxValueIndex = 0;for (int i = 0; i < nums.size(); i++) {if (nums[i] > maxValue) {maxValue = nums[i];maxValueIndex = i;}}node->val = maxValue;// 最大值所在的下标左区间 构造左子树if (maxValueIndex > 0) {vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);node->left = constructMaximumBinaryTree(newVec);}// 最大值所在的下标右区间 构造右子树if (maxValueIndex < (nums.size() - 1)) {vector<int> newVec(nums.begin() + maxValueIndex + 1, nums.end());node->right = constructMaximumBinaryTree(newVec);}return node;}
};

​ 提升代码性能,重写函数,整体代码如下:

class Solution{
private:TreeNode* traversal(vector<int>& nums, int left, int right){if(left >= right)	return NULL;// 分割点下标:maxValueIndexint maxValueIndex = left;for (int i = left + 1; i < right; ++i) {//理解递归思路if (nums[i] > nums[maxValueIndex]) maxValueIndex = i;}TreeNode* root = new TreeNode(nums[maxValueIndex]);// 左闭右开:[left, maxValueIndex)//无须判断节点是否为空,因为可以允许空节点进入root->left = traversal(nums, left, maxValueIndex);// 左闭右开:[maxValueIndex + 1, right)root->right = traversal(nums, maxValueIndex + 1, right);return root;}
public:TreeNode* constructMaximumBinaryTree(vector<int>& nums){return traversal(nums, 0, nums.size());}
};

合并二叉树

给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。

你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。

示例 1:

617.合并二叉树

注意: 合并必须从两个树的根节点开始。

​ 看起来操作两个二叉树第一次见,实际上在对称二叉树中已经使用过类似的思路了;

​ 合并二叉树,只需要同时遍历两个二叉树就可以了:

​ 代码实现(前序)如下:

class Solution {
public:TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1// 修改了t1的数值和结构t1->val += t2->val;                             // 中t1->left = mergeTrees(t1->left, t2->left);      // 左t1->right = mergeTrees(t1->right, t2->right);   // 右return t1;}
};

​ 本题前中后序都是可以的,前序最好理解;

​ 也可以采取构造新节点的方法:

class Solution {
public:TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {if (t1 == NULL) return t2;if (t2 == NULL) return t1;// 重新定义新的节点,不修改原有两个树的结构TreeNode* root = new TreeNode(0);root->val = t1->val + t2->val;root->left = mergeTrees(t1->left, t2->left);root->right = mergeTrees(t1->right, t2->right);return root;}
};

二叉搜索树中的搜索

给定二叉搜索树(BST)的根节点和一个值。 你需要在BST中找到节点值等于给定值的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 NULL。

例如,

700.二叉搜索树中的搜索

在上述示例中,如果要找的值是 5,但因为没有节点值为 5,我们应该返回 NULL。

​ 二叉搜索树是一个有序树:

​ 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

​ 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

​ 它的左、右子树也分别为二叉搜索树;

例如,

[外链图片转存中…(img-V4uavmvL-1712591045263)]

在上述示例中,如果要找的值是 5,但因为没有节点值为 5,我们应该返回 NULL。

​ 二叉搜索树是一个有序树:

​ 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;

​ 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

​ 它的左、右子树也分别为二叉搜索树;

​ 这就决定了,二叉搜索树,递归遍历和迭代遍历和普通二叉树都不一样;

但是因为有序这一特性的存在,代码写起来是很简洁的;

	TreeNode* searchBST(TreeNode* root, int val){//函数参数和返回值//终止条件if(root == NULL || root->val == val)	return root;//中if(root->val > val)	return searchBST(root->left, val);//左if(root->val < val)	return searchBST(root->right, val);//右return NULL;}

​ 也可以用迭代法实现:

	TreeNode* searchBST(TreeNode* root, int val){while(root != NULL){if(root->val > val)	root = root->left;else if(root->val < val)	root = root->right;else return root;}return NULL;}

验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

  • 节点的左子树只包含小于当前节点的数。
  • 节点的右子树只包含大于当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

98.验证二叉搜索树

​ 直观想法:中序遍历二叉树,判断数组是否递增即可;

	vector<int> res;	bool traversal(TreeNode* root){if(root == NULL)	return true;//空节点什么二叉树都是isBST(root->left);res.push_back(root->val);isBST(root->right);        }traversal(root);for (int i = 1; i < vec.size(); i++) {// 注意要小于等于,搜索树里不能有相同元素if (vec[i] <= vec[i - 1]) return false;}return true;

​ 若不使用数组辅助直接对二叉树进行操作,如何判断?

​ 很直白的一个想法

	if(root->val > root->left->val && root->val < root->right->val)	return ture;

​ **这么写就错了!**因为需要满足的不仅是大于子节点数值,而是整个子树节点的元素;

​ 这里可以采取一个最小值的全局变量,也可以直接使用双指针的思路来优化:

class Solution {
public:TreeNode* pre = NULL;bool isValidBST(TreeNode* root){if(root == NULL)    return true;bool left = isValidBST(root->left);if(pre != NULL && pre->val >= root->val)	return false;//当前一个节点大于等于后一个节点的时候,return false;pre = root;//记录前一个节点bool right = isValidBST(root->right);return left && right;}
};

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

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

相关文章

【鸿蒙千帆起】《开心消消乐》完成鸿蒙原生应用开发,创新多端联动用户体验

《开心消消乐》已经完成鸿蒙原生应用开发&#xff0c;乐元素成为率先完成鸿蒙原生应用开发的20游戏厂商之一。作为一款经典游戏&#xff0c;《开心消消乐》已经拥有8亿玩家&#xff0c;加入鸿蒙原生应用生态&#xff0c;将为其带来更优的游戏性能和更多创新体验。自9月25日华为…

中国500米分辨率月最大EVI数据集

增强型植被指数&#xff08;EVI&#xff09;是在归一化植被指数&#xff08;NDVI&#xff09;改善出来的&#xff0c;根据大气校正所包含的影像因子大气分子、气溶胶、薄云、水汽和臭氧等因素进行全面的大气校正&#xff0c;EVI大气校正分三步&#xff0c;第一步是去云处理。第…

【SQL Sever】3. 用户管理 / 权限管理

1. 创建登录名/用户/角色 在SQL Server中&#xff0c;创建用户通常涉及几个步骤。 首先&#xff0c;你需要创建一个登录名&#xff0c;然后你可以基于这个登录名在数据库中创建一个用户。 以下是如何做到这一点的步骤和相应的SQL语句&#xff1a; 创建登录名 首先&#xff0c…

Python零基础从小白打怪升级中~~~~~~~文件和文件夹的操作 (1)

第七节&#xff1a;文件和文件夹的操作 一、IO流&#xff08;Stream&#xff09; 通过“流”的形式允许计算机程序使用相同的方式来访问不同的输入/输出源。stream是从起源&#xff08;source&#xff09;到接收的&#xff08;sink&#xff09;的有序数据。我们这里把输入/输…

企业鸿蒙原生应用元服务备案实操基本材料要求

一、要提前准备的主要材料包括 域名&#xff0c;服务器&#xff0c;包名&#xff0c;公钥&#xff0c;MD5值&#xff0c;法人身份证正反两面&#xff0c;邮箱&#xff0c;手机号2个。 域名是备案过的&#xff0c;应为要求域名能打开&#xff0c;还要悬挂备案号。 操作时要提前沟…

目标检测——瓶装白酒疵品检测数据集

一、重要性及意义 瓶装白酒疵品检测在白酒生产过程中具有极其重要的地位&#xff0c;其重要性和意义主要体现在以下几个方面&#xff1a; 首先&#xff0c;瓶装白酒疵品检测是保障消费者权益的关键环节。白酒作为消费者日常饮用的酒类之一&#xff0c;其品质直接关系到消费者…

【电控笔记4】拉普拉斯-传递函数-pid

数据标幺化 拉普拉斯变换 欧拉公式 常见s变换 s变换性质 pid分析 p控制&#xff0c;存在稳态误差 可以求出p的取值范围p>-1&#xff0c;否则发散 pi消除稳态误差 把kp换成Gs 只用pi控制&#xff0c;不加微分的原因&#xff1a; 微分之后&#xff0c;噪声增大高频噪声频率…

【研发管理】产品经理知识体系-数字化战略

导读: 数字化战略对于企业的长期发展具有重要意义。实施数字化战略需要企业从多个方面进行数字化转型和优化&#xff0c;以提高效率和创新能力&#xff0c;并实现长期竞争力和增长。 目录 1、定义 2、数字化战略必要性 3、数字战略框架 4、数字化转型对产品和服务设计的影响…

卷积通用模型的剪枝、蒸馏---剪枝篇(此处以deeplabv3+为例,可根据模型自行定制剪枝层)

之后的两篇文章是对前段时间工作的一个总结。 一、环境配置 1.1、文章以b导的代码为模板,环境配置比较简单(第二篇蒸馏篇结束后会放置剪枝蒸馏配置好的百度网盘链接),其他算法自行配置,在剪枝之前,需要保证算法能够在本地跑通。 B导链接: https://github.com/bubbliiiin…

行云堡垒国密算法应用与信创支持

一、 国密算法和信创的介绍 1.1 什么是国密算法 国密算法是国家密码管理局制定颁布的一系列的密码标准&#xff0c;即已经被国家密码局认定的国产密码算法&#xff0c;又称商用密码&#xff08;是指能够实现商用密码算法的加密&#xff0c;解密和认证等功能的技术&#xff09;…

.NET邮箱API发送邮件的流程?如何使用API?

.NET邮箱API发送邮件需要哪些步骤&#xff1f;怎么配置API发信&#xff1f; 电子邮件已经成为我们日常工作和生活中不可或缺的一部分。对于开发人员来说&#xff0c;掌握如何使用API发送邮件是一项非常实用的技能。AokSend将详细介绍使用.NET邮箱API发送邮件的流程&#xff0c…

机器学习和深度学习 -- 李宏毅(笔记与个人理解1-6)

机器学习和深度学习教程 – 李宏毅&#xff08;笔记与个人理解&#xff09; day1 课程内容 什么是机器学习 找函数关键技术&#xff08;深度学习&#xff09; 函数 – 类神经网络来表示 &#xff1b;输入输出可以是 向量或者矩阵等如何找到函数&#xff1a; supervised Lear…

电感在 DC/DC 变换器中的作用及选型指南

消费类应用是现代 DC/DC 变换器需求的主要驱动力。在这类应用中&#xff0c;功率电感主要被用于电池供电设备、嵌入式计算&#xff0c;以及高功率、高频率的 DC/DC 变换器。了解电感的电气特性对于设计紧凑型、经济型、高效率、并具备出色散热性能的系统至关重要。 电感是一种…

3D模型可视化引擎HOOPS Visualize如何实现大型工厂可视化管理?

随着工业技术的不断发展&#xff0c;大型工厂的管理和运营面临着越来越多的挑战。为了提高效率、降低成本和优化生产流程&#xff0c;工厂管理者越来越倾向于采用先进的可视化技术来进行工厂管理。在这一领域中&#xff0c;3D模型可视化引擎HOOPS Visualize正发挥着越来越重要的…

Java项目:基于SSM+vue框架实现的人力资源管理系统设计与实现(源码+数据库+毕业论文+任务书)

一、项目简介 本项目是一套基于SSM框架实现的人力资源管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、功能…

数据结构排序之冒泡、快速、插入、选择、堆、归并等排序及时间,空间复杂度等(超详解,绝对能满足你的需求,并能学到很多有用知识)

在本文章开始之前给大家介绍个网站,可以通过下面动画网址来理解 ,(国外的网站帮助学习数据结构很多知识,可以翻译下来,在搜索框搜索相应的排序算法进行动画演示,非常好用。)​​​https://www.cs.usfca.edu/~galles/visualization/https://www.cs.usfca.edu/~galles/vis…

物联网实战--驱动篇之(七)RTC时钟(DS1302)

目录 一、RTC简介 二、DS1302介绍 三、初始化 四、字节读写 五、功能函数 一、RTC简介 实时时钟&#xff0c;简称RTC&#xff0c;这个在STM32的外设里也有&#xff0c;不过STM32F1系列的RTC实际上只有一个计数器功能&#xff0c;如果需要年月日要自己写软件计算 &#xff…

CDR2024破解序列号Crack免费下载最新CorelDraw2024安装包

CorelDRAW是一款功能强大的矢量图形制作和排版软件&#xff0c;主要面向绘图设计师和印刷输出人员。它提供了一整套的绘图工具&#xff0c;包括圆形、矩形、多边形、方格、螺旋线等&#xff0c;并配合塑形工具&#xff0c;可以对各种基本图形作出更多的变化&#xff0c;如圆角矩…

基于Lipschitz李式指数的随机信号特征识别和故障检测matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 Lipschitz李式指数定义与性质 4.2 Lipschitz李式指数的估计 4.3 Lipschitz李式指数在信号特征识别与故障检测中的应用 5.完整程序 1.程序功能描述 基于Lipschitz李式指数的随机信号特…

HD哈默纳科行星减速机:工业传动领域的卓越之选

HD哈默纳科行星减速机泛应用于各种工业领域的传动装置&#xff0c;以其卓越的性能和稳定的表现赢得了用户的广泛认可。HD哈默纳科行星减速机减速机具有结构紧凑、高减速比、高精度、负载能力强、耐久性好等诸多特点&#xff0c;使其在各类机械设备中发挥着至关重要的作用。 HD…