代码随想录算法训练营:17/60

非科班学习算法day17 | LeetCode654:最大二叉树 ,Leetcode617:合并二叉树 ,Leetcode700:二叉搜索树中的搜索,Leetcode98:验证二叉搜索树 

目录

介绍

一、基础概念补充:

1.二叉搜索树

二、LeetCode题目

1.LeetCode654:最大二叉树

题目解析

 2.Leetcode617:合并二叉树 

题目解析

3.Leetcode700:二叉搜索树中的搜索

题目解析

 

4.Leetcode98:验证二叉搜索树

题目解析

总结


介绍

包含LC的两道题目,还有相应概念的补充。

相关图解和更多版本:

代码随想录 (programmercarl.com)https://programmercarl.com/#%E6%9C%AC%E7%AB%99%E8%83%8C%E6%99%AF


一、基础概念补充:

1.二叉搜索树

二叉搜索树(Binary Search Tree,简称BST),又称有序二叉树或排序二叉树,是一种特殊的二叉树数据结构,它具有以下基本性质:

  1. 节点值的有序性

    • 节点的左子树中所有节点的值都小于该节点的值。
    • 节点的右子树中所有节点的值都大于该节点的值。
  2. 唯一性

    • 二叉搜索树中不允许有重复的节点值,即每个值都是唯一的。
  3. 递归定义

    • 整个树要么为空,要么满足以上两个性质,并且左子树和右子树也必须分别是二叉搜索树。

由于这些性质,二叉搜索树支持一些非常高效的算法,例如:

  • 查找:从根节点开始,比较当前节点的值与目标值,根据大小关系决定向左子树还是右子树递归查找,时间复杂度在最佳情况下为O(log n),最坏情况下为O(n)(当树退化为链表时)。

  • 插入:类似于查找,找到合适的位置后创建新节点插入,同时保持树的性质不变。

  • 删除:删除操作相对复杂,需要考虑被删除节点是否有子节点,以及如何调整树结构以保持二叉搜索树的性质,可能包括寻找前驱或后继节点来替代被删除节点。

相关性质还包括:

  • 中序遍历二叉搜索树的中序遍历(左根右的顺序)会得到一个递增的序列,这是其有序性的直接体现,也是验证一个二叉树是否为二叉搜索树的一个简单方法。

  • 高度:二叉搜索树的高度与其节点插入的顺序有关,最坏情况下(每次插入的节点都是当前树的最大或最小值,导致树变为链式结构)高度为n,最好情况下接近log(n)。

为了优化性能,特别是减少高度,发展出了多种平衡二叉搜索树,如AVL树、红黑树等,它们通过额外的平衡条件和旋转操作来保证树的高度大致保持在对数级别,从而确保各种操作的平均时间复杂度为O(log n)。  

二、LeetCode题目

1.LeetCode654:最大二叉树

题目链接:654. 最大二叉树 - 力扣(LeetCode)

题目解析

       可以发现这道题和106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)非常相似,都是在所给的数组上做文章来构建树,那么具体如何操作呢。

        首先需要一个函数来寻找最大值

        然后根据信息创建节点

        之后根据最大值位置分割数组

        最后将得到的数组进行下一层递归

所以中止条件也应该是数组无法分割。

 c++代码如下:

/*** 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() == 1)return new TreeNode(nums[0]);// 寻找最大值 -----重置初始化!!!------int max_val = 0;int max_pos = 0;for (int i = 0; i < nums.size(); ++i) {if (nums[i] > max_val) {max_pos = i;max_val = nums[i];}}// 创建节点TreeNode* root = new TreeNode(max_val);// 分割数组// vector<int> left_nums = vector<int>(nums.begin(),// nums.begin()+max_pos); vector<int> right_nums =// vector<int>(nums.begin()+max_pos+1, nums.end());// 递归if (max_pos > 0) {vector<int> left_nums =vector<int>(nums.begin(), nums.begin() + max_pos);root->left = constructMaximumBinaryTree(left_nums);}if (max_pos < nums.size() - 1) {vector<int> right_nums =vector<int>(nums.begin() + max_pos + 1, nums.end());root->right = constructMaximumBinaryTree(right_nums);}return root;}
};

注意点1:这里把寻找最大值函数放到里面了,尽量减少函数调用,同时还有个问题就是经过修改研究,尽量减少函数调用可以避免由于传入参量和调用函数之间发生冲突甚至未定义重定义等现象。

注意点2:注意在寻找最大值之前要把参数重新初始化,否则这种写法就会报错。

注意点3:关于中止条件,根据题目条件数组长度是一定大于等于1的,而且调试的时候发现用空来做,自己出了错,所以直接采用等于1时候,直接返回自身。

 2.Leetcode617:合并二叉树 

题目链接:617. 合并二叉树 - 力扣(LeetCode)

题目解析

       一开始考虑的特别复杂,其实根据题目描述,我们不需要完全新建一棵树,而且那样的空间消耗明显更多。所以进行分类讨论:

        左节点空,右节点不空,返回右节点

        右节点空,左节点不空,返回左节点

        左右节点都为空,返回空

        左右节点不为空,做加和操作,新建节点

        递归下一层的两个树对应位置

c++代码如下:

/*** 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* dfs(TreeNode* root1, TreeNode* root2) {// 左空右回if (root1 && !root2)return root1;// 右空左回if (!root1 && root2)return root2;// 空返回if (!root1 && !root2)return nullptr;// 非空做加和// 中int sum_num = root1->val + root2->val;// 创建新节点TreeNode* new_root = new TreeNode(sum_num);// 左new_root->left = dfs(root1->left, root2->left);// 右new_root->right = dfs(root1->right, root2->right);// 返回二叉树的新根节点return new_root;}TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {return dfs(root1, root2);}
};

3.Leetcode700:二叉搜索树中的搜索

题目链接:700. 二叉搜索树中的搜索 - 力扣(LeetCode)

题目解析

       二叉搜索树由于特性的存在,在搜索的时候,不用整棵树都搜索,每次判断之后,只需要选择一边递归。

C++代码如下:

/*** 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* searchBST(TreeNode* root, int val) {if (!root)return nullptr;// 需要明确,写递归的时候是有条件的,不需要全部都搜索if (root->val == val)return root;if (root->val > val && root->left)return searchBST(root->left, val);if (root->val < val && root->right)return searchBST(root->right, val);return nullptr;}
};

注意点1:最后的返回值是null,而且递归函数如果有返回类型一定要用东西接住,要么return,要么赋值给其他变量。

 

4.Leetcode98:验证二叉搜索树

题目链接:98. 验证二叉搜索树 - 力扣(LeetCode)

题目解析

       最直接的做法就是根据二叉搜索树的性质进行中序遍历,然后检验结果是否是一个递增数组。

        优化思路就是,借助一个新的自定义指针来记录每一次在遍历过程中的节点,作为下一次递归的前一个结点,这样我们再次中序遍历,就可以直接比较前后两个节点的结果。最后返回值是左右两边共同检查的交。

C++代码如下:

/*** 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:vector<int> res;vector<int> dis(TreeNode* root) {if (!root)return res;dis(root->left);res.push_back(root->val);dis(root->right);return res;}bool isValidBST(TreeNode* root) {dis(root);for (int i = 0; i < res.size() - 1; ++i) {if (res[i] >= res[i + 1])return false;}return true;}
};

 记录指针中序遍历c++代码:

/*** 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* pre = nullptr;bool isValidBST(TreeNode* root) {// 现在要做的就是检索,然后if (!root)return true;// 还是中序遍历bool left = isValidBST(root->left);if (pre && pre->val >= root->val) //先写赋值,转头再想return false;pre = root;bool right = isValidBST(root->right);return left && right;}
};

总结


打卡第17天,坚持!!!

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

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

相关文章

价格!六安市各地双软(软件企业、软件产品)办理流程步骤及申报材料、时间

六安市各地双软&#xff08;软件企业、软件产品&#xff09;办理流程步骤材料 &#xff08;更多问题详情可以查看小编主页方式&#xff09; 第一步&#xff1a;办理软件企业认定 1.打开办理软件企业认定的中心网站&#xff0c;然后注册并登录&#xff0c;下载双软认定申报表…

大数据系统软件助力工业数字化转型

随着科技的不断进步&#xff0c;大数据系统软件在工业领域的应用日益广泛&#xff0c;成为推动工业数字化转型的关键技术之一。工业数字化转型旨在通过技术手段提升生产效率、优化资源配置&#xff0c;并提供智能决策支持&#xff0c;从而实现更高效、可持续的生产模式。 数据采…

Kafka 集群如何处理生产者和消费者处理消息速率差异问题?

kafka 集群如何处理生产者和消费者处理消息速率差异问题? Kafka 集群通过多种机制来处理生产者和消费者处理消息速率的差异问题,确保消息的高效传递和系统的 稳定性。以下是详细的解释和机制: 1. 消息缓冲机制 Kafka 使用消息缓冲机制来处理生产者和消费者速率的不匹配。…

接口测试中遇到的sessionID验证问题

在接口测试中&#xff0c;经常会存在联调的接口&#xff0c;比如登录完去调用其他的接口&#xff0c;这时就会存在一个问题&#xff0c;那就是登录成功了&#xff0c;但是其他接口失败了&#xff0c;这个时候就需要用到一个sessionID去传入其他接口验证合法性请求&#xff0c;这…

k8s重启后报错Error getting node not found

今天升级一台3主的k8s集群的配置。升级其中一台后另外两个节点就出现Not Ready的状态。 升级之前最好把一些能停的应用停掉。或者能够通过增加临时节点来进行扩容&#xff0c;不然所有pod调度到其他节点&#xff0c;可能把其他节点压垮。没办法&#xff0c;只能把其他两台直接…

Python学习前简介

1.python简介 2.python特点 3.python解释器 4.pyCharm简介 一、python简介 Python是一种高级编程语言&#xff0c;用于多种应用&#xff0c;包括网站开发、数据科学、人工智能、机器学习、桌面应用、网络应用、软件开发、网络爬虫等。它由Guido van Rossum于1991年首次发布&am…

group by和select的兼容性问题

group by和select的兼容性问题 在标准的SQL语法中&#xff0c;GROUP BY 和 SELECT 之间不存在兼容性问题&#xff0c;因为它们是 SQL 查询语句的基本组成部分&#xff0c;而且它们的使用方式是相互兼容的。 SELECT 子句和 GROUP BY 子句的关系&#xff1a; SELECT 子句&#…

Matlab进阶绘图第61期—滑珠散点图

滑珠散点图也是一种在《Nature》中常见的数据图。 其功能类似于柱状图&#xff0c;但更加简洁易读。 由于Matlab中没有现成的函数绘制滑珠散点图&#xff0c;因此需要大家自行解决。 本文利用自己制作的BubbleScatter工具&#xff0c;进行滑珠散点图的绘制&#xff0c;先来看…

【山东大学项目实训】进度汇报16

进行了带有历史记录的问答链的修改优化 Chat_QA_chain_self from langchain.chains import ConversationalRetrievalChain from qa_chain.model_to_llm import model_to_llm from qa_chain.get_vectordb import get_vectordbclass Chat_QA_chain_self:"""&quo…

ServBay[中文] 下一代Web开发环境

ServBay是一个集成式、图形化的本地化Web开发环境。开发者通过ServBay几分钟就能部署一个本地化的开发环境。解决了Web开发者&#xff08;比如PHP、Nodejs&#xff09;、测试工程师、小型团队安装和维护开发测试环境的问题&#xff0c;同时可以快速的进行环境的升级以及维护。S…

头歌Python作业——8.1 模拟生成身份信息及查验身份(project)

目录 第1关 第2关 第3关 第4关 第1关 import random def person_name(gender_of_id, last_name_file, male_name_file, female_name_file):"""参数 gender_of_id&#xff1a;性别&#xff0c;字符串类型参数 last_name_file&#xff1a;百家姓文件名&…

Chrome开发者工具学习

打开开发者工具&#xff1a; 可以通过在网页上点击右键并选择“检查”来打开。 或者使用快捷键Ctrl Shift I&#xff08;在Windows/Linux上&#xff09;或Command Option I&#xff08;在Mac上&#xff09;。 界面概览&#xff1a; 熟悉DevTools的基本面板&#xff0c;如“…

【精品案例】数字孪生技术与数字工厂案例(59页PPT)

引言&#xff1a;随着工业4.0和智能制造的快速发展&#xff0c;数字孪生技术和数字工厂已成为制造业转型升级的重要趋势。数字孪生技术通过构建虚拟的数字模型&#xff0c;实现对物理实体全生命周期的映射与仿真&#xff0c;为企业的产品研发、设计、制造等提供有力支持。而数字…

【AI大模型应用开发】3. RAG初探 - 动手实现一个最简单的RAG应用

0. 什么是RAG 大模型也不是万能的&#xff0c;也有局限性。 LLM 的知识不是实时的LLM 可能不知道你私有的领域/业务知识 RAG&#xff08;Retrieval Augmented Generation&#xff09;顾名思义&#xff1a;通过检索的方法来增强生成模型的能力。你可以把这个过程想象成开卷考…

MATLAB算法实战应用案例精讲-【数模应用】线性判别分析(附MATLAB、python和R语言代码实现)

目录 前言 算法原理 什么是判别分析 线性判别分析(LDA) 数学模型 二分类 多分类LDA ​编辑 算法思想: 费歇(FISHER)判别思想 贝叶斯(BAYES)判别思想 LDA算法流程 LDA与PCA对比 SPSSPRO 1、作用 2、输入输出描述 3、案例示例 4、案例数据 5、案例操作 …

VC++开发积累——vc++6.0中删除函数的方法,右键,Delete

目录 引出插曲&#xff1a;删除函数的方法多行注释的实现代码输入的自动提示搜索出来&#xff0c;标记和取消标记跳转到上一步的位置 ctrl TAB 总结其他规范和帮助文档创建第一个Qt程序对象树概念信号signal槽slot自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自…

SQL中limit用法记录

在SQL中&#xff0c;LIMIT 子句主要用于限制SELECT语句返回的结果集中的行数。这对于分页显示数据、获取固定数量的最新记录或其他需要控制输出结果规模的情况非常有用。以下是LIMIT在不同SQL数据库中的基本用法&#xff1a; MySQL和其他兼容SQL方言&#xff08;如SQLite&…

DM达梦数据库字符串函数整理

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

python基础篇(5):None类型

1 None类型 Python中有一个特殊的字面量&#xff1a;None&#xff0c;其类型是&#xff1a;<class NoneType> 无返回值的函数&#xff0c;实际上就是返回了&#xff1a;None这个字面量 None表示&#xff1a;空的、无实际意义的意思 函数返回的None&#xff0c;就表示…

压力测试原理

压力测试的原理 压力测试是一种软件测试方法&#xff0c;其目的是评估系统或应用程序在高负载或极端工作条件下的性能、稳定性和可靠性。它的原理在于模拟真实或预期的大量用户同时或频繁地访问系统&#xff0c;以此来检测系统是否能够处理这些请求&#xff0c;是否存在瓶颈&a…