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

ops/2024/9/24 13:21:38/

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);}
}

http://www.ppmy.cn/ops/93031.html

相关文章

第二章 部署LVS-DR

DR模式的调度器和节点服务器都有VIP地址&#xff0c;但节点服务器的VIP在回环网卡&#xff0c;回环网卡的地址只能本机看到&#xff0c;外部主机看不到&#xff0c;所以不会冲突。 一、DR模式的简单过程 DR模式的具体过程&#xff1a;首先客户端.135向目标vip发出请求&#x…

2-17、18 HC06蓝牙模块(meArm机械臂)

2-17、18 HC06蓝牙模块&#xff08;meArm机械臂&#xff09; 2-17 HC06蓝牙模块-1RX引脚分压电路HC06连接与arduino的电路HC06蓝牙模块应用程序测试程序1&#xff1a;使用Arduino通过无线蓝牙控制Arduino引脚11的LED点亮&#xff0f;熄灭测试程序2&#xff1a;使用Arduino通过无…

67、ceph

一、ceph 1.1、ceph概念 ceph是一个开源的&#xff0c;用c语言写的分布式的存储系统。存储文件数据。 /dev/sdb fdisk /dev/sdb gdisk /dev/sdb lvm 逻辑卷 可以扩容 raid 磁盘阵列 高可用 基于物理意义上的单机的存储系统。 分布式有多台物理磁盘组成一个集群&…

编程-设计模式 23:模板方法模式

设计模式 23&#xff1a;模板方法模式 定义与目的 定义&#xff1a;模板方法模式定义了一个操作中的算法骨架&#xff0c;而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。目的&#xff1a;该模式的主要目的是封装算法的…

从入门到精通:接入视频美颜SDK与直播美颜插件详解

本篇文章&#xff0c;笔者将为你详细解析美颜SDK从入门到精通的全过程&#xff0c;帮助你轻松掌握这项技术。 一、什么是视频美颜SDK与直播美颜插件&#xff1f; 视频美颜SDK是一组预构建的代码库和工具&#xff0c;开发者可以将其嵌入到移动应用或平台中&#xff0c;从而实现…

haproxy原理及实验演示(实现服务器集群的负载均衡)

haproxy介绍 HAProxy是一个使用C语言编写的自由及开放源代码软件&#xff0c;由法国人Willy Tarreau开发。它是一款高性能的TCP和HTTP负载均衡器&#xff0c;特别适用于那些负载特大的web站点&#xff0c;这些站点通常又需要会话保持或七层处理&#xff08;这是他和lvs功能上的…

预测云计算的未来

云计算的未来是否依旧未知&#xff1f; 直到最近&#xff0c;云计算还是软件编程界之外很少有人熟悉的一个概念。如今&#xff0c;云计算已成为一切的基础&#xff0c;从点播电视服务和在线游戏门户网站到电子邮件和社交媒体&#xff0c;这四大现代世界的基石。云计算将继续存在…

江科大/江协科技 STM32学习笔记P20

文章目录 编码器接口测速定时器有关的库函数Encoder.cmain.c 编码器接口测速 编码器接口的初始化&#xff0c;第一步&#xff0c;RCC开启时钟&#xff0c;开启GPIO和定时器的时钟&#xff0c;第二步&#xff0c;配置GPIO&#xff0c;这里把PA6和PA7配置成输入模式&#xff0c;第…