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

代码随想录算法训练营十七天|二叉树part07

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

题目链接:235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode)

给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

示例 1:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
输出: 6 
解释: 节点 2 和节点 8 的最近公共祖先是 6。
示例 2:

输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
输出: 2
解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。

 可以直接用之前写的二叉树的最近公共祖先的解法解决,但因为是二叉搜索树,所以可以利用一些二叉搜索树的特性。

因为是有序树,所以如果root的值介于p,q的值的中间,那么root一定是p,q的最近公共祖先;如果p,q的值都小于root的值,那么说明p,q的最近公共祖先一定在root的左子树上;同理,如果p,q的值都大于root的值,那么说明p,q的最近公共祖先一定在root的右子树上。

代码如下:

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {//递归法if((p.val<=root.val&&q.val>=root.val)||(p.val>=root.val&&q.val<=root.val))return root;else if(p.val<root.val&&q.val<root.val)return lowestCommonAncestor(root.left,p,q);else if(p.val>root.val&&q.val>root.val)return lowestCommonAncestor(root.right,p,q);return null;}
}

迭代法也很简单:

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {//迭代法while(root!=null){if((p.val<=root.val&&q.val>=root.val)||(p.val>=root.val&&q.val<=root.val))return root;else if(p.val<root.val&&q.val<root.val)root=root.left;else if(p.val>root.val&&q.val>root.val)root=root.right;}return null;}
}

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

题目链接:701. 二叉搜索树中的插入操作 - 力扣(LeetCode)

给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。

示例 1:


输入:root = [4,2,7,1,3], val = 5
输出:[4,2,7,1,3,5]
解释:另一个满足题目要求可以通过的树是:

示例 2:

输入:root = [40,20,60,10,30,50,70], val = 25
输出:[40,20,60,10,30,50,70,null,null,25]
示例 3:

输入:root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
输出:[4,2,7,1,3,5]

 这里不考虑题目中所说的改变树的结构的插入方式,直接按照二叉搜索树的规则去遍历,遇到空节点插入就行了。

递归代码如下:

class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {//递归TreeNode node=new TreeNode(val);if(root==null){root=node;return root;}search(root,node);return root;}public void search(TreeNode root,TreeNode node){if(root.left==null&&node.val<root.val)root.left=node;if(root.right==null&&node.val>root.val)root.right=node;if(node.val>root.val)search(root.right,node);else if(node.val<root.val)search(root.left,node);}
}

对于迭代法,需要记录当前遍历的节点的父节点,需要用到pre和Newroot两个新的节点。和之前做过的二叉搜索树的最小绝对差、二叉树的众数技巧相似。

代码如下: 

class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {//迭代TreeNode node=new TreeNode(val);if(root==null)return node;TreeNode pre=null;TreeNode Newroot=root;while(Newroot!=null){pre=Newroot;if(Newroot.val>val)Newroot=Newroot.left;else if(Newroot.val<val)Newroot=Newroot.right;}if(pre.val>val)pre.left=node;else if(pre.val<val)pre.right=node;return root;}
}

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

题目链接:450. 删除二叉搜索树中的节点 - 力扣(LeetCode)

给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

首先找到需要删除的节点;
如果找到了,删除它。

示例 1:

输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。


示例 2:

输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点
示例 3:

输入: root = [], key = 0
输出: []

 首先要明白删除节点有几种情况:

1.没找到删除的节点,遍历到空节点直接返回;

2.找到删除的节点,该节点左右孩子都为空,说明是叶子节点,直接删除即可;

3.删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位;

4.删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位;

5.删除节点的左右孩子都不为空,则将删除节点的左子树的头节点放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。

第五种情况示例动画如下:

这是因为二叉搜索树的特性,对于删除节点来说,它的右子树上的值都大于删除节点的值,左子树上的值都小于删除节点的值,所以左子树上的最大值小于右子树上的最小值,所以左子树的头结点要放到右子树最左面节点的左孩子上,这样才能保证二叉树的特性不变。

知道了这五种情况之后,递归代码就好写了:

class Solution {public TreeNode deleteNode(TreeNode root, int key) {//递归if(root==null)return null;if(root.val==key){if(root.left==null)return root.right;else if(root.right==null)return root.left;else{TreeNode tmp=root.right;while(tmp.left!=null){tmp=tmp.left;}tmp.left=root.left;root=root.right;return root;}}else if(root.val<key)root.right=deleteNode(root.right,key);else root.left=deleteNode(root.left,key);return root;}
}

 迭代法依然要用到两个额外的节点,pre用来保存前序节点:

class Solution {public TreeNode deleteNode(TreeNode root, int key) {//迭代if (root == null)return null;TreeNode tmp = root;TreeNode pre = null;while (tmp != null) {if (tmp.val > key) {pre = tmp;tmp = tmp.left;} else if (tmp.val < key) {pre = tmp;tmp = tmp.right;} elsebreak;}if (pre == null)return delete(tmp);if (pre.left != null && pre.left.val == key) {pre.left = delete(tmp);}if (pre.right != null && pre.right.val == key) {pre.right = delete(tmp);}return root;}public TreeNode delete(TreeNode node){if(node==null)return null;if(node.right==null)return node.left;TreeNode cur=node.right;while(cur.left!=null){cur=cur.left;}cur.left=node.left;node=node.right;return node;}
}

http://www.dtcms.com/a/282394.html

相关文章:

  • 【android bluetooth 协议分析 03】【蓝牙扫描详解 2】【app触发蓝牙扫描后,协议栈都做了那些事情】
  • 跨平台 App 如何无痛迁移到鸿蒙系统?全流程实战+Demo 教程
  • 八股文——包装类
  • Android 升级targetSdk无法启动服务
  • 动态规划题解——分割等和子集【LeetCode】
  • 面向向量检索的教育QA建模:九段日本文化研究所日本语学院的Prompt策略分析(6 / 500)
  • 知识点3:python-sdk 核心概念(prompt、image、context)
  • 有哪些好用的原型设计软件?墨刀、Axure等测评对比
  • MAC 苹果版Adobe Photoshop 2019下载及保姆级安装教程!!
  • Prompt Engineering 快速入门+实战案例
  • C#.NET BackgroundService 详解
  • 增程式汽车底盘设计cad【9张】三维图+设计说明书
  • 机器学习sklearn入门:归一化和标准化
  • 深入解析 AWS RDS Proxy
  • VirtualBox 中 CentOS 7 双网卡配置静态 IP
  • 用 Ray 跨节点调用 GPU 部署 DeepSeek 大模型,实现分布式高效推理
  • 「计算机网络」笔记(一)
  • qt 中英文翻译 如何配置和使用
  • 面试150 二叉树的锯齿层次遍历
  • YOLO13正式发布!考虑将yolov13的创新点融合到半监督中,构建YOLOv13_ssod
  • Qt 将触摸事件转换为鼠标事件(Qt4和Qt5及以上版本)
  • Qt 的信号槽机制中,使用 `connect` 函数时,第五个参数是 **连接类型(Connection Type)**,
  • Ubuntu中man手册不全解决以及man手册中英文切换方法
  • 若依框架下前后端分离项目交互流程详解
  • 20、鸿蒙Harmony Next开发:组件导航(Navigation)和页面路由(@ohos.router)
  • 现代人工智能综合分类:大模型时代的架构、模态与生态系统
  • Node.js ORM框架Sequelize 一对一(One-to-One)、一对多(One-to-Many)和多对多(Many-to-Many)
  • NDVI、噪声和细微差别:使用卫星时间序列进行土地覆盖分类
  • K近邻算法的分类与回归应用场景
  • LVS集群调度器