LeetCode 450.删除二叉搜索树中的节点和669.修建二叉搜索树思路对比 及heap-use-after-free问题解决

题目描述 

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

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

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

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

示例 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]。

669.修建二叉搜索树

给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

示例 1:

输入:root = [1,0,2], low = 1, high = 2
输出:[1,null,2]

示例 2:

输入:root = [3,0,4,null,2,null,null,1], low = 1, high = 3
输出:[3,2,null,1]

思路对比

450题目在处理的时候需要分为五种情况,因为它需要改变子树的结构并且改变的方式不唯一:

第一种是二叉搜索树中不存在要寻找的节点

第二种是需要删除叶子节点

第三种是要删除的节点只有左子叶,没有右子叶

第四种是只有右子叶,没有左子叶

第五种是最难处理的,左右子叶都有,加入上图中要删除的节点是7,对于这一种情况处理的方式是选择右子叶9作为新的代替7的节点,然后将5 4 6这一左子树移动到8底下,也就是9这个子树下最小的数字。从代码上编写,就是一直向左搜寻,搜寻到叶子节点为止,就找到8了。

而669题目中说不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案 。这道题出现第五种情况时与上一题不同的地方在于,如果当前节点小于low,那么它的整个左子树都需要被裁剪,如果大于high,整个右子树也需要被裁减,所以它不需要像上一题的第五种情况一样,对整个树的结构进行大的改变。当前节点小于low,就直接将上一节点指向右子树(右子树的值也需要裁剪)

代码实现

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

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* deleteNode(TreeNode* root, int key) {if(root == NULL) return NULL;if(root->val == key){if(root->left == NULL && root->right == NULL) return NULL;else if(root->left != NULL && root->right == NULL) return root->left;else if(root->right != NULL && root->left == NULL) return root->right;else{TreeNode* cur = root->right;while(cur->left){cur = cur->left;}cur->left = root->left;return root->right;}}if(root->val > key){root->left = deleteNode(root->left,key);}if(root->val < key){root->right = deleteNode(root->right,key);}return root;}
};

669. 修剪二叉搜索树

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* trimBST(TreeNode* root, int low, int high) {if(root == NULL) return NULL;if(root->val < low){TreeNode* right = trimBST(root->right,low,high);return right;}if(root->val >high){TreeNode* left = trimBST(root->left,low,high);return left;}root->left = trimBST(root->left,low,high);root->right = trimBST(root->right,low,high);return root;}
};

heap-use-after-free问题

开始解决669问题时完全套用450的思路,代码如下,出现了报错 

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:TreeNode* trimBST(TreeNode* root, int low, int high) {if(root == NULL) return NULL;if(root->val < low || root->val > high){if(root->left == NULL && root->right == NULL) return NULL;else if(root->left != NULL && root->right == NULL) return root->left;else if(root->right != NULL && root->left == NULL) return root->right;else{TreeNode* cur = root->right;while(cur->left){cur = cur->left;}cur->left = root->left;return root->right;}}root->left = trimBST(root->left,low,high);root->right = trimBST(root->right,low,high);return root;}
};

发现问题出现在尾节点root->left本来有值,但是现在将它的节点全都转移到其他地方了,要将这个尾节点指向NULL就行,修改代码如下:

else{TreeNode* cur = root->right;while(cur->left){cur = cur->left;}cur->left = root->left;root->left = NULL;return root->right;}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/260725.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 使用documents4j将XML转为pdf文件的方式

1.背景&#xff1a; 通过spire.doc.free将word转换成PDF时存在缺陷&#xff1a;只能获取前3页。获取全文另外需支付费用。 2.解决办法 使用documents4j&#xff0c;documents4j会保留原word文件中更多的样式&#xff0c;如修订模式下的差异化字体颜色、文档右侧修订记录等。 …

掌握Go并发:Go语言并发编程深度解析

&#x1f3f7;️个人主页&#xff1a;鼠鼠我捏&#xff0c;要死了捏的主页 &#x1f3f7;️系列专栏&#xff1a;Golang全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

【Docker】集群容器监控和统计 Portainer基本用法

Portainer是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用川于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 主要功能&#xff1a;实现集群容器的监控和统计 下载安装 官网&#xff1a;https://www.portainer.io 文档&#xff1a;https://do…

C#分部类的应用:记录学生信息

目录 一、分部类及其用途 二、实例 再发一个分部类的应用&#xff0c;巩固一下。 一、分部类及其用途 C#中的部分类也被称为分部类。 C#中的部分类是一种将类的定义分成多个部分&#xff0c;每个部分都位于自己的文件中&#xff0c;然后在编译时合并在一起的机制。 部分类…

(十)【Jmeter】线程(Threads(Users))之jp@gc - Stepping Thread Group (deprecated)

简述 操作路径如下: 作用:通过逐步增加线程数来模拟用户并发访问。配置:设置This group will start、First,wait for 、Then start、Next , add等参数。使用场景:模拟逐步增长的并发访问,观察应用程序的性能变化。优点:适用于测试应用程序在逐步增加负载下的性能表现。…

stm32——hal库学习笔记(定时器)

这里写目录标题 一、定时器概述&#xff08;了解&#xff09;1.1&#xff0c;软件定时原理1.2&#xff0c;定时器定时原理1.3&#xff0c;STM32定时器分类1.4&#xff0c;STM32定时器特性表1.5&#xff0c;STM32基本、通用、高级定时器的功能整体区别 二、基本定时器&#xff0…

智慧城市与数字孪生:实现城市可持续发展的关键

一、引言 随着全球城市化进程的加速&#xff0c;城市面临着诸多挑战&#xff0c;如资源紧张、环境恶化、交通拥堵等。为了解决这些问题&#xff0c;智慧城市的概念应运而生。智慧城市利用先进的信息通信技术&#xff0c;提升城市治理水平&#xff0c;改善市民的生活质量。而数…

[C#]winform基于opencvsharp结合pairlie算法实现低光图像增强黑暗图片变亮变清晰

【低光图像增强介绍】 在图像处理领域&#xff0c;低光图像增强是一个具有挑战性的任务。由于光线不足&#xff0c;这些图像往往呈现出低对比度、高噪声和细节丢失等问题&#xff0c;严重影响了图像的视觉效果和后续分析的准确性。因此&#xff0c;开发有效的低光图像增强方法…

Redis(03)——发布订阅

基础命令 基于频道 publish channel message&#xff1a;将信号发送到指定的频道pubsub subcommand [argument [argyment]]&#xff1a;查看订阅或发布系统状态subscribe channel [channel]&#xff1a;订阅一个或多个频道的信息unsubscribe [channel [channel]]&#xff1a;退…

SpringBootWeb学习笔记——12万字详细总结!

0. 写在前面 注:这套笔记是根据黑马程序员B站2023-3-21的视频学习的成果,其中省略了前端基础部分、Maven部分和数据库基础部分,详情可见目录。 注注:目前文章内结尾处多幅图片加载不出来,因为图片还存在本地没被传上来,过段时间再改~ 所有的Spring项目都基于Spring Fra…

Vue路由组件练习

Vue 路由组件练习 1. 演示效果 2. 代码分析 2.1. 安装 vue-router 命令&#xff1a;npm i vue-router 应用插件&#xff1a;Vue.use(VueRouter) 2.2. 创建路由文件 在 src 文件夹下&#xff0c;创建router文件夹&#xff0c;并在该文件夹创建index.js文件 2.3. 导入依赖…

解决vscode每次git pull/push都需要输入账号密码

git如何设置用户名 邮箱 密码 //设置用户 git config --global user.name "xxx"//设置邮箱 git config --global user.email "xxxxxx.com"//设置密码 git config --global user.password "xxxxx"解决每次git pull/push操作都需要输入密码 git …

ctfshow-web29~40-WP

web29 if(isset($_GET[c])){$c = $_GET[c];if(!preg_match("/flag/i", $c)){eval($c);}}else{highlight_file(__FILE__); } 首先先system(“ls”);查看一下文件 既然过滤了flag,那我们就fla*的形式进行匹配,结合tac命令输出flag.php文件内容

Collection集合体系(ArrayList,LinekdList,HashSet,LinkedHashSet,TreeSet,Collections)

目录 一.Collection 二.List集合 三.ArrayList集合 四.LinkedList集合 五.Set集合 六.hashSet集合 七.LinkedHashSet集合 八.TreeSet集合 九.集合工具类Collections 集合体系概述 单列集合&#xff1a;Collection代表单列集合&#xff0c;每个元素&#…

2024牛客寒假算法基础集训营4(视频讲解题目)

2024牛客寒假算法基础集训营4&#xff08;视频讲解题目&#xff09; 视频链接ABCDEFG、H&#xff08;下面是hard版本的代码两个都可以过&#xff09; 视频链接 2024牛客寒假算法基础集训营4&#xff08;视频讲解题目&#xff09; A #include<bits/stdc.h> #define en…

Linux(五)__系统管理

介绍 通常&#xff0c; Windows 中使用"任务管理器"主要有 3 个目的&#xff1a; 利用"应用程序"和"进程"标签来査看系统中到底运行了哪些程序和进程&#xff1b;利用"性能"和"用户"标签来判断服务器的健康状态&#xff1…

【c++】vector的增删查改

1.先定义一个类对象vector 为了防止和库里面发生冲突&#xff0c;定义一个命名空间&#xff0c;将类对象放在命名空间 里面 #include<iostream> using namespace std; namespace zjw {class vector {public:private:}; }2.定义变量&#xff0c;需要一个迭代器&#xff…

Python开发户型图编辑器-2D/3D户型图展示

在现代家居设计中&#xff0c;户型图是不可或缺的工具&#xff0c;它为设计师和业主提供了一个直观的展示和规划空间的方式。然而&#xff0c;传统的户型图编辑软件往往复杂难用&#xff0c;限制了设计师的创作灵感。我们为您带来了一款全新的Python开发的户型图编辑器&#xf…

IDEA中创建web项目(配置tomcat,tomcat启动报程序包javax.servlet.http不存在,tomcat控制台乱码问题)

文章目录 一、新建动态web项目1、新建项目2、选择创建动态web项目3、项目命名4、编辑index.jsp 二、配置Tomcat1、新增tomcat服务器配置2、选择服务器类型3、配置服务器参数4、部署项目5、完成配置6、启动运行7、访问web项目 三、tomcat启动报程序包javax.servlet.http不存在四…

数组的左旋和右旋算法

public class Test09 {public static void main(String[] args) {//右旋 数组逆序遍历&#xff0c;将尾部元素&#xff0c;不断交换至头部int[] arr {1,2,3,4,5,6,7,8};for(int i arr.length-1;i>0;i--) { //遍历一次arr[i] arr[i] ^ arr[i-1];arr[i-1] arr[i] ^ arr[i…