当前位置: 首页 > 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.lryc.cn/news/589906.html

相关文章:

  • LeafletJS 入门:构建你的第一个交互式地图
  • 【无标题】LighthouseGS:面向全景式移动拍摄的室内结构感知三维高斯泼溅
  • Day36 Java方法和流程控制练习 计算器
  • 微软AutoGen:多智能体协作的工业级解决方案
  • ESP32——快速入门
  • 外接硬盘写入速度很慢?Windows 写入缓存功能开启教程!
  • 知识点3:python-sdk 核心概念(prompt、image、context)
  • 项目学习笔记 display从none切换成block
  • 尚庭公寓-------图片上传接口
  • 2025年工会考试题库及答案
  • alpineLinux修改包管理为国内源
  • 详解SPFA算法-单源最短路径求解
  • 陆面、生态、水文模拟与多源遥感数据同化的实践技术应用
  • 【图灵完备】算数运算
  • sktime - 时间序列机器学习统一接口
  • 控制Vue对话框显示隐藏
  • C++设计模式之创建型模式
  • 【机器学习】数据理解:数据导入、数据审查与数据可视化
  • 数据降维方法:PCA
  • 集训Day02笔记总结(关于一些OJ题目的)
  • 第四章 OB SQL调优
  • Taro.eventCenter 用法详解与实战
  • DAY8-在地下城寻求邂逅Python是否搞错了什么
  • JavaScript语言 Error对象及错误处理机制 原生错误类型
  • Matlab数字图像处理——基于图像分割与模板匹配的的车牌识别系统
  • orfeotoolbox ResetMargin
  • mongoDB初始化项目简单操作示例
  • Windows 启动后桌面黑屏,其他程序正常运行
  • ARCGIS PRO DSK 颜色选择控件(ColorPickerControl)的调用
  • MySQL 8.0 OCP 1Z0-908 题目解析(28)