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

【数据结构与算法 | 力扣+二叉搜索树篇】力扣450, 98

1. 力扣450:删除二叉搜索树的节点

1. 题目:

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

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

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

示例 1:

e6a16dc3738a4e91b547ba349bea5bcd.jpeg

输入: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
输出: []

提示:

  • 节点数的范围 [0, 104].
  • -105 <= Node.val <= 105
  • 节点值唯一
  • root 是合法的二叉搜索树
  • -105 <= key <= 105

进阶: 要求算法时间复杂度为 O(h),h 为树的高度。

2. 题解

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {TreeNode root1;public TreeNode deleteNode(TreeNode root, int key) {root1 = root;TreeNode p = root;TreeNode parent = null;while (p != null) {if (p.val > key) {parent = p;p = p.left;} else if (p.val < key) {parent = p;p = p.right;} else {break;}}if (p == null) {return root;}if (p.left == null && p.right == null) {shift(parent, p, null);} else if (p.left != null && p.right == null) {shift(parent, p, p.left);} else if (p.left == null && p.right != null) {shift(parent, p, p.right);} else {TreeNode s = p.right;TreeNode sParent = p;while (s.left != null) {sParent = s;s = s.left;}if (p != sParent) {shift(sParent, s, s.right);s.right = p.right;}shift(parent, p, s);s.left = p.left;}return root1;}public void shift(TreeNode parent, TreeNode deleted, TreeNode child) {if (parent == null) {root1 = child;} else if (parent.left == deleted) {parent.left = child;} else {parent.right = child;}}
}

2. 力扣98 :验证二叉搜索树

1. 题目:

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

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

  • 节点的左

    子树

    只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

a0d64713dd2c49d1b3a537973809ef35.jpeg

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

示例 2:

51b6a1398ce04a01bfe1762ca55c3571.jpeg

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

提示:

  • 树中节点数目范围在[1, 104] 内
  • -231 <= Node.val <= 231 - 1

2.思路(递归):

对于该题我们可以使用递归的方法去解决。由于二叉搜索树的特性,一个节点比其左孩子的值要大,比右孩子的要小(如果其有左右孩子的话),但由此条件是不够推出其是二叉搜索树的。如果某节点的值满足比其左子树的最大值要大,比其右子树的最小值要小,并且其左孩子和右孩子都满足该规则的话,是可以推出该是一个有效的二叉搜索树的。

3. 题解:

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public boolean isValidBST(TreeNode root) {return doisValidBST(root);}public boolean doisValidBST(TreeNode node) {// 如果是空树,直接返回if(node == null) {return true;}boolean flag = true;TreeNode p = null;// 该节点存在左子树的前提下,满足节点比左子树所有节点的最大值要大if ((p = node.left) != null) {while(p.right != null) {p = p.right;}flag = p.val < node.val ? true : false;}// 如果flag为false,就不必要进行下列的判断了if(flag){//在节点存在右子树的前提下,满足节点比右子树的所有节点的最小值要小if ((p = node.right) != null) {while(p.left != null) {p = p.left;}flag = p.val > node.val ? true : false;}}if(node.left == null && node.right == null) {return flag;} else if (node.left != null && node.right == null) {return flag==true && isValidBST(node.left);} else if (node.left == null && node.right != null) {return flag && isValidBST(node.right);} else {return flag && isValidBST(node.left) && isValidBST(node.right);}}
}

4. 思路(有序递增数列)

由题可知,中序遍历得到的序列一定是递增数列。

5. 题解:

class Solution {Deque<Integer> deque = new LinkedList<>();public boolean isValidBST(TreeNode root) {midTraverse(root);while (!deque.isEmpty()){int i1 = deque.pop();if(deque.isEmpty()){return true;}int i2 = deque.peek();if(i2 >= i1){return false;}}return true;}private void midTraverse(TreeNode node) {if (node == null) {return;}midTraverse(node.left);deque.push(node.val);midTraverse(node.right);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++中的::
  • 告别DockerHub 镜像下载难题:掌握高效下载策略,畅享无缝开发体验
  • 【Python深度学习】如何实现将将时间序列转换为图像的功能
  • 基于python的电商水果超市的设计与实现
  • 手机游戏录屏软件哪个好,3款软件搞定游戏录屏
  • Golang | Leetcode Golang题解之第327题区间和的个数
  • 数据库系统 第2节 数据库语言
  • 一篇文章教会你 LVS———NAT模式和DR模式部署配置
  • 【ES6】使用Set和Map进行全组合判断
  • Java微服务生态系统构建指南
  • 《PostgreSQL 中通过函数实现不确定列的数据更新操作》
  • MYSQL 删除一个字段前,判断字段是否存在
  • 高级Web安全技术(第二篇)
  • C#学习笔记16:串口上位机数据绘图助手Plotter的开发
  • 如何学好uni-app
  • [笔记] php常见简单功能及函数
  • Apache的80端口被占用以及访问时报错403
  • C++类的相互关联
  • dva中组件的懒加载
  • HashMap剖析之内部结构
  • jquery ajax学习笔记
  • Redux 中间件分析
  • Sass Day-01
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 如何合理的规划jvm性能调优
  • 系统认识JavaScript正则表达式
  • 想写好前端,先练好内功
  • 因为阿里,他们成了“杭漂”
  • 从如何停掉 Promise 链说起
  • 如何在招聘中考核.NET架构师
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ​configparser --- 配置文件解析器​
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #{} 和 ${}区别
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • (03)光刻——半导体电路的绘制
  • (145)光线追踪距离场柔和阴影
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)计算机毕业设计ssm电影分享网站
  • (含笔试题)深度解析数据在内存中的存储
  • (汇总)os模块以及shutil模块对文件的操作
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .net core + vue 搭建前后端分离的框架
  • .NET Core Web APi类库如何内嵌运行?
  • .net core 使用js,.net core 使用javascript,在.net core项目中怎么使用javascript
  • .Net Core中Quartz的使用方法
  • .NET中统一的存储过程调用方法(收藏)
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)
  • []我的函数库
  • [ACM独立出版] 2024年虚拟现实、图像和信号处理国际学术会议(VRISP 2024,8月2日-4)