当前位置: 首页 > news >正文

算法day18|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

算法day18|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点

  • 235. 二叉搜索树的最近公共祖先
    • 1.一般性解法
    • 2.递归法
    • 3.迭代法
  • 701.二叉搜索树中的插入操作
    • 1.递归法
    • 2.迭代法
  • 450.删除二叉搜索树中的节点

235. 二叉搜索树的最近公共祖先

1.一般性解法

class Solution {
public:TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q){if(root==NULL)return root;if(root==p||root==q)return root;TreeNode* left=traversal(root->left,p,q);TreeNode* right=traversal(root->right,p,q);if(left!=NULL&&right!=NULL)return root;else if(left==NULL&&right!=NULL)return right;else if(left!=NULL&&right==NULL)return left;elsereturn NULL;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return traversal(root,p,q);}
};

注意

else if(left!=NULL&&right==NULL)return left;

这里返回的是left,而不是root->left。我们需要返回的是从左孩子传上来的值,而不是左孩子结点。

2.递归法

class Solution {
public:TreeNode* traversal(TreeNode* root, TreeNode* p, TreeNode* q){if(root==NULL)return NULL;if(root->val>p->val&&root->val>q->val){TreeNode*left=traversal(root->left,p,q);if(left!=NULL)return left;}else if(root->val<p->val&&root->val<q->val){TreeNode*right=traversal(root->right,p,q);if(right!=NULL)return right;}return root;}TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {return traversal(root,p,q);}
};

二叉搜索树的另一个利用思路:除了利用二叉树搜索树的中序遍历之外,我们也可以直接利用二叉搜索树在树上的性质:左<中<右。由于没有用到中序遍历的递增序列,所以在递归的时候可以不使用中序遍历,直接用它的性质来接就行了

核心思路:如果结点值 > p和q的值,那么说明p和q在该节点左边,所以需要向左递归;如果结点值 < p和q的值,那么说明p和q在该节点右边,所以需要向右递归;如果节点值在p和q之间,那么这个结点就是最近的公共祖先。

代码细节:如果函数有返回值,那么在if和else之外一定还需要有一个return,所以这样是错的:

else if(root->val<p->val&&root->val<q->val){TreeNode*right=traversal(root->right,p,q);if(right!=NULL)return right;}
elsereturn root;}

但是改成这样就对了,在 if 和 else 之外再加一个return:

else if(root->val<p->val&&root->val<q->val){TreeNode*right=traversal(root->right,p,q);if(right!=NULL)return right;}
else
{return root;
}     return NULL;}

3.迭代法

class Solution {
public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {while(root!=NULL){if(root->val>p->val&&root->val>q->val){root=root->left;}else if(root->val<p->val&&root->val<q->val){root=root->right;}elsereturn root;}return NULL;}
};

701.二叉搜索树中的插入操作

1.递归法

比较简单,代码如下:

class Solution {
public:void traversal(TreeNode* &root, int val){if(root==nullptr){root=new TreeNode(val);return;}if(root->val<val){if(root->right)traversal(root->right,val);else{TreeNode*node=new TreeNode(val);root->right=node;}}if(root->val>val){if(root->left)traversal(root->left,val);else{TreeNode*node=new TreeNode(val);root->left=node;}}return;}TreeNode* insertIntoBST(TreeNode* root, int val) {traversal(root,val);return root;}
};

**核心思路:**当结点值 > root,且右孩子不为空,则向右递归。若右孩子为空,则直接插入,作为该节点的右孩子;当节点值 < root时同理。

易错:

void traversal(TreeNode* &root, int val)

这里需要“带回去”,所以要加上&。

2.迭代法

class Solution {
public:TreeNode* insertIntoBST(TreeNode* root, int val) {if(root==nullptr){root=new TreeNode(val);return root;}TreeNode*cur=root;TreeNode*parent=cur;while (cur != NULL) {parent = cur;if (cur->val > val) cur = cur->left;else cur = cur->right;}TreeNode*node=new TreeNode(val);if(parent->val<val)parent->right=node;elseparent->left=node;return root;}
};

思路与递归法一致。

450.删除二叉搜索树中的节点

这题难度不小,第一遍尽量理解:

class Solution {
public:TreeNode* traversal(TreeNode* root, int key){if(root==nullptr)return nullptr;if(root->val==key){if(root->left==nullptr&&root->right==nullptr){delete root;return nullptr;}else if(root->left!=nullptr&&root->right==nullptr){TreeNode*temp=root->left;delete root;return temp;}else if(root->left==nullptr&&root->right!=nullptr){TreeNode*temp=root->right;delete root;return temp;}else if(root->left!=nullptr&&root->right!=nullptr){TreeNode*cur=root->right;TreeNode*temp=root->right;while(cur->left)cur=cur->left;cur->left=root->left;delete root;return temp;}}if(root->val>key)root->left=traversal(root->left,key);if(root->val<key)root->right=traversal(root->right,key);return root;}TreeNode* deleteNode(TreeNode* root, int key) {return traversal(root,key);}
};

总体思路:

  • 参数和返回值正常

  • 终止条件:

    这题的终止条件是重中之重,因为核心条件的判断也纳入了终止条件,即只要符合某种条件就终止。这个条件就是节点值等于key,因为只要节点值等于key就不用再继续递归了。所以真正删除的核心操作就在终止条件里,一共有4种情况:

    • 左右孩子都空,即为叶节点

    • 左孩子空,右孩子不空

    • 左孩子不空,右孩子空

    • 左右孩子都不空(注意这里可以有两种处理逻辑,只要能满足二叉搜索树的定义即可

  • 单层递归逻辑:不用对当前结点做处理,只有满足一定条件时才会有处理(即终止条件)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • SpringBoot 数据访问-jpa
  • 旋转编码器模块(软件消抖)
  • LVGL | VisualStuio PC模拟器
  • 【机器学习】集成学习------迅速了解什么是集成学习!!!
  • 子组件和父组件的挂载顺序
  • 微信小程序认证和备案
  • c++ 编译器的不同处理阶段详解
  • Open3D 点云添加均匀分布的随机噪声
  • Spring Cloud各个微服务之间为什么要用http交互?难道不慢吗?
  • camtasia studio字幕位置怎么移动 camtasia studio字幕有黑框怎么删除黑框
  • oracle 数据库安装与配置 全新教程
  • nestjs目录命名导致的循环引用
  • 2024嵌入式面试:比亚迪嵌入式面试题及参考答案(BYD面试)
  • 数据安全与个人信息保护的辨析
  • 数据结构---五大排序---哈希表---二分查找法
  • SegmentFault for Android 3.0 发布
  • Apache Zeppelin在Apache Trafodion上的可视化
  • classpath对获取配置文件的影响
  • Fabric架构演变之路
  • interface和setter,getter
  • js写一个简单的选项卡
  • Mithril.js 入门介绍
  • MySQL QA
  • text-decoration与color属性
  • vue-router 实现分析
  • 成为一名优秀的Developer的书单
  • 好的网址,关于.net 4.0 ,vs 2010
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 计算机常识 - 收藏集 - 掘金
  • 配置 PM2 实现代码自动发布
  • 软件开发学习的5大技巧,你知道吗?
  • 三分钟教你同步 Visual Studio Code 设置
  • 算法-图和图算法
  • 异常机制详解
  • 如何在招聘中考核.NET架构师
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​​​​​​​GitLab 之 GitLab-Runner 安装,配置与问题汇总
  • # SpringBoot 如何让指定的Bean先加载
  • #我与Java虚拟机的故事#连载03:面试过的百度,滴滴,快手都问了这些问题
  • (02)vite环境变量配置
  • (1)STL算法之遍历容器
  • (Oracle)SQL优化基础(三):看懂执行计划顺序
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (强烈推荐)移动端音视频从零到上手(上)
  • (十一)手动添加用户和文件的特殊权限
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .mysql secret在哪_MySQL如何使用索引
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .net SqlSugarHelper