【三十二】【算法分析与设计】深搜(2),98。 验证二叉搜索树,不同方式定义递归函数,230。 二叉搜索树中第 K 小的元素,257。 二叉树的所有路径

98. 验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左

  • 子树

  • 只包含 小于 当前节点的数。

  • 节点的右子树只包含 大于 当前节点的数。

  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

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

示例 2:

输入:root = [5,1,4,null,null,3,6] 输出:false 解释:根节点的值是 5 ,但是右子节点的值是 4 。

提示:

  • 树中节点数目范围在[1, 10(4)]

  • -2(31) <= Node.val <= 2(31)1

两个递归

定义 isValidBSTHelper 递归函数,判断 root 树是否是二叉搜索树。

维护递归定义内部逻辑,左子树是二叉搜索树,右子树也是二叉搜索树,同时自身也是二叉搜索树,此时 return true

判断左右子树是不是二叉搜索树,交给递归函数即可,我们只需要判断自身是否为二叉搜索树。

如果左子树的所有值都小于 root->val,右子树的所有值都大于 root->val,此时自身也是二叉搜索树。

递归出口,root==nullptr,return true

定义递归函数 dfs,判断 root 树是否在范围(minVal,maxVal)之中。

维护递归定义内部逻辑,root->val 在范围内,左子树和右子树也在范围内。

递归的出口,如果 root==nullptr,return true

 
/*** 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 isValidBST(TreeNode* root) { return isValidBSTHelper(root); }private:bool isValidBSTHelper(TreeNode* node) {if (node == nullptr)return true;return isValidBSTHelper(node->left) && isValidBSTHelper(node->right) &&dfs(node->left, LONG_MIN, node->val) &&dfs(node->right, node->val, LONG_MAX);}bool dfs(TreeNode* root, long minVal, long maxVal) {if (root == nullptr)return true;if (root->val <= minVal || root->val >= maxVal)return false;return dfs(root->left, minVal, maxVal) &&dfs(root->right, minVal, maxVal);}
};

节点正确存在

另一种递归思维,定义递归函数 isValidBSTHelper 判断 node 这棵树的全部节点是否正确存在。

root 是否是二叉搜索树,取决于 root 这棵树的的所有节点是否正确存在。

维护递归的内部逻辑,node 这棵树全部节点是否正确存在,如果左子树全部节点正确存在,右子树全部节点正确存在,node 根节点也正确存在,那么就算全部正确存在。

node 根节点是否正确存在,取决于他的父亲结点,父亲节点会给予一个范围,如果在父亲结点的左子树,那么 node->val 必须小于父亲结点的 val,如果在父亲结点的右子树,那么 node->val 必须大于父亲结点的 val

递归的出口,如果 node==nullptr,return true

 
/*** 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 isValidBST(TreeNode* root) {return isValidBSTHelper(root, LONG_MIN, LONG_MAX);}private:bool isValidBSTHelper(TreeNode* node, long minVal, long maxVal) {if (node == nullptr)return true;if (node->val <= minVal || node->val >= maxVal)return false;return isValidBSTHelper(node->left, minVal, node->val) &&isValidBSTHelper(node->right, node->val, maxVal);}
};

中序遍历有序

利用二叉搜索树的性质判断。二叉搜索树中序遍历的结果是有序序列。

root 是否是二叉搜索树,取决于 root 这棵树的中序遍历序列是否有序。

定义递归函数 isValidBST 判断 root 树中序遍历序列是否是有序序列。

定义 prev 表示前驱节点的值。

维护定义的内部逻辑,判断左子树中序遍历序列是否是有序序列,判断 root 根节点的值是否大于前驱节点的值。然后再判断右子树中序遍历序列是否是有序序列。

递归出口,如果 root==nullptr,return true

剪枝操作,如果左子树中序遍历序列不是有序,说明 root 这棵树中序不是有序,直接返回 false

如果 root 根节点的值小于等于前驱节点,说明 root 这棵树中序不是有序,直接返回 false

如果右子树中序遍历序列不是有序,说明 root 这棵树中序不是有序,直接返回 false

 
/*** 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 {long prev = LONG_MIN;public:bool isValidBST(TreeNode* root) {if (root == nullptr)return true;bool leftbool = isValidBST(root->left);if (leftbool == false)return false;bool cur = false;if (root->val > prev)cur = true;if (cur == false)return false;prev = root->val;bool rightbool = isValidBST(root->right);if (rightbool == false)return false;return true;}
};

230. 二叉搜索树中第 K 小的元素

给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

示例 1:

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

示例 2:

输入:root = [5,3,6,2,4,null,null,1], k = 3 输出:3

提示:

  • 树中的节点数为 n

  • 1 <= k <= n <= 10(4)

  • 0 <= Node.val <= 10(4)

进阶:如果二叉搜索树经常被修改(插入/删除操作)并且你需要频繁地查找第 k 小的值,你将如何优化算法?

二叉搜索树的性质,中序遍历序列是有序的。

定义递归函数 dfs,先遍历左子树,再遍历自己,再遍历右子树。

定义全局变量 count retcount 记录还剩需要遍历节点数量,ret 记录最终答案。

 
/*** 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 count;int ret;int kthSmallest(TreeNode* root, int k) {count = k;dfs(root);return ret;}void dfs(TreeNode* root) {if (root == nullptr)return;dfs(root->left);count--;if (count == 0)ret = root->val;dfs(root->right);return;}
};

257. 二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

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

示例 1:

输入:root = [1,2,3,null,5] 输出:["1->2->5","1->3"]

示例 2:

输入:root = [1] 输出:["1"]

提示:

  • 树中节点的数目在范围 [1, 100]

  • -100 <= Node.val <= 100

定义递归函数 dfs,将 root 这棵树的所有路径填充到 ret 中。

定义 path 存储当前节点到一开始的 root 根节点的路径。

维护递归函数的内部逻辑,首先维护 path 变量,使 path 变量存储当前节点到一开始的 root 根节点的路径。

然后再判断此时是否是叶子节点,如果会死叶子节点说明 path 是其中一个有效的路径,填充到 ret 中。

如果不是叶子节点,path 路径后面添加->

然后将左子树路径填充到 ret 中,右子树路径填充到 ret 中。

递归出口,如果 root==0,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:vector<string> ret;vector<string> binaryTreePaths(TreeNode* root) {// 定义dfs找到所有路径,填充到ret中// 定义path 存储当前状态路径string path;dfs(root, path);return ret;}void dfs(TreeNode* root, string path) {if (root == nullptr)return;path += to_string(root->val);if (root->left == nullptr && root->right == nullptr)ret.push_back(path);path += "->";if (root->left)dfs(root->left, path);if (root->right)dfs(root->right, path);}
};

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

小程序 两页面间数据传递

页面1 页面2 实现效果&#xff1a;点击页面1 可以直接跳进页面2 实现过程&#xff1a; xhtml <view class"rank" wx:for"{{rankList}}" data-ids"{{item.id}}" data-names"{{item.name}}" data-description"{{item.descri…

行测——言语分析

行测——言语分析 1. 全文概括题1.1 做题思路1.2 例子1.2.1 概括内容1.2.2 标题类 2.中心理解题2.1 做题思路2.2 例子2.2.1 关键词清晰2.2.2 关键词不清晰 3. 逻辑顺序题3.1 做题思路3.2 例子3.2.1 划线部分填什么句子3.2.2 句子排序3.2.3 下一段讲什么3.2.4 细节分析题 4. 逻辑…

Oracle基础-PL/SQL编程 备份

1、PL/SQL简介 PL/SQL块结构 约定&#xff1a;为了方便&#xff0c;本文后面把PL/SQL简称PL。 PL程序都是以块&#xff08;BLOCK&#xff09;为基本单位&#xff0c;整个PL块分三部分&#xff1a;声明部分&#xff08;使用DECLARE开头&#xff09;、执行部分(以BEGIN开头)和异…

数字人视频合成平台推荐

数字人讲解视频和全景作品的结合是一种全新的数字交互方式&#xff0c;可为用户提供更加直观和具有沉浸感的内容展示和交互体验&#xff0c;从而适用于诸如旅游、展览、博物馆、教育培训、泛房地产、以及娱乐和文化等应用场景。 当前数字人合成视频技术已经发展至日益成熟的阶…

SSL通配符证书怎么选?看这里

通配符证书&#xff0c;作为一种特殊的数字证书类型&#xff0c;以其独特的优势在网络安全领域扮演着重要角色。相较于传统的单一域名证书&#xff0c;通配符证书能够为同一主域名下的所有子域名提供安全保护&#xff0c;显著提升管理效率&#xff0c;简化证书部署流程&#xf…

LandCover数据介绍与下载

一、LC介绍 土地覆盖&#xff08;Land Cover&#xff0c;LC&#xff09;是自然营造物和人工建筑物所覆盖的地表诸多要素的综合体。土地覆盖指地表所属的植被覆盖物(森林、草原、耕作植被等)或非植被覆盖物(冰雪、建筑物等)的具体类型&#xff0c;侧重描述地球表面的自然属性&a…

02 - 全加器和加法器

---- 整理自B站UP主 踌躇月光 的视频 1. 全加器 用门电路实现两个二进制数相加并求出和的组合线路&#xff0c;称为一位全加器。一位全加器可以处理低位进位&#xff0c;并输出本位加法进位。全加器比半加器多了一位进位。 1.1 实验 1&#xff1a;通过两个半加器设计全加器 1.…

IDEA无法连接虚拟机中的Redis的解决方案,无法连接Jedis,无法ping通虚拟机的解决方案

首先&#xff0c;笔者先说明一下自身的情况&#xff0c;怎么连接都连不上&#xff0c;网上的教程全部都看了一遍&#xff0c;基本上没用得上的&#xff0c;这篇文章里面的解决方案包括了笔者能在网上找到了最全面的办法总结&#xff0c;最后终于是连上了 目录 一.连接Jedis出错…

Linux初学(十一)中间件

一、web服务 1.1 中间件简介 中间件其实就是一类软件&#xff0c;中间件的作用是让用户可以看到一个网页 总结&#xff1a;客户端可以向服务端发送请求&#xff0c;服务器端会通过中间件程序来接收请求&#xff0c;然后处理请求&#xff0c;最后将处理结果返回给客户端 1.2 中…

自动驾驶的世界模型:综述

自动驾驶的世界模型&#xff1a;综述 附赠自动驾驶学习资料和量产经验&#xff1a;链接 24年3月澳门大学和夏威夷大学的论文“World Models for Autonomous Driving: An Initial Survey”。 在快速发展的自动驾驶领域&#xff0c;准确预测未来事件并评估其影响的能力对安全性…

C++ 2024-4-2 作业

1.模板类实现顺序栈 #include <iostream> #define MAX 8 using namespace std; template<typename T> class stack {T data[MAX];int top; public:stack():top(-1){}bool empty_stack();bool full_stack();void push_stack(T data);void pop_stack();void show();…

OpenMLDB vs Redis 内存占用量测试报告

1. 背景 OpenMLDB 是一款开源的高性能全内存 SQL 数据库&#xff0c;在时序数据存储、实时特征计算等方面都有很多创新和优化。Redis 是业界最流行的内存存储数据库&#xff0c;广泛应用于缓存等高性能在线场景。虽然二者应用场景不尽相同&#xff0c;但作为都是使用内存作为存…

docker容器之etcd安装

一、etcd介绍 1、etcd是什么 etcd是CoreOS团队于2013年6月发起的开源项目&#xff0c;它的目标是构建一个高可用的分布式键值(key-value)数据库。 2、etcd特点 简单的接口&#xff0c;通过标准的HTTP API进行调用&#xff0c;也可以使用官方提供的 etcdctl 操作存储的数据。…

使用Vue实现CSS过渡和动画

01-初识动画和过渡 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>使用vue实现css过渡和动画&l…

MMU关闭时Cache的缓存策略是怎样的

快速链接: 【精选】ARMv8/ARMv9架构入门到精通-[目录] &#x1f448;&#x1f448;&#x1f448; 在学习MMU章节时&#xff0c;我们发现在页表的entry中&#xff0c;BIT[4:2]指向了MAIR寄存器&#xff0c;该寄存器描述了内存属性&#xff0c;其实就是cache的缓存策略属性&#…

高性价比的挂耳式耳机哪个好用?五大高口碑品牌深度测评严选!

入耳式耳机虽然普及度极高&#xff0c;但其缺点也不容忽视。首先&#xff0c;长时间佩戴可能导致耳朵不适&#xff0c;甚至影响听力健康。其次&#xff0c;入耳式耳机往往因为隔音效果过好&#xff0c;导致用户与周围环境脱节&#xff0c;失去了一定的生活便利性。相比之下&…

《书生·浦语大模型全链路开源开放体系》学习笔记

书生浦语大模型全链路开源开放体系-学习笔记 大模型成为发展通用人工智能的重要途径专用模型通用大模型 书生大模型开源历程InternLM2回归语言建模的本质主要亮点性能全方位提升强大的内生计算能力 从模型到应用典型流程全链条开源开放体系数据数据集获取预训练微调XTuner 评测…

Runes 生态一周要览 ▣ 2024.3.25-3.31|Runes 协议更新 BTC 减半在即

Runes 生态大事摘要 1、Casey 发布了 Runes 协议文档 RUNES HAVE DOCS&#xff0c;Github 代码库更新到 ord 0.17.0 版本&#xff0c;Casey 表示符文是一个“严肃”的代币协议。 2、Casey 公布了第一个硬编码的创世符文「UNCOMMONGOODS」 3、4月7日香港沙龙&#xff5c;聚焦「…

c++的学习之路:9、STL简介与string(1)

一、STL 1、什么是STL STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。 也就是说STL就是一个模板&#xff0c;这个模板就是整合了很多库让我们方…

Git常用语句

设置用户名 git config --global user.name "用户名" git config --global user.email "邮箱"查看git用户信息 cat ~/.gitconfig初始化本地库 git initclone指定分支的代码 git clone -b my_branch gitgitlabxxxxxxxxxxxxxxxxxxxxxx.gitpush三件套 gi…