文章目录

  • 二叉树的最近公共祖先
  • 二叉搜索树的最近公共祖先
  • 二叉搜索树中的插入操作
  • 删除二叉搜索树中的节点

二叉树的最近公共祖先

题目链接:236. 二叉树的最近公共祖先

解题逻辑:

最近公共祖先的定义为:对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)

我们想要寻找两个节点的最近公共祖先,是一个从下向上寻找的过程,那么我们可以通过递归中的归来解决(向下递,向上归)。

我们可以通过两种思路来解决这个问题:

  • 递归的返回值的传递
  • 回溯算法

这两种思路都可以实现从下到上的逻辑处理。

这里我们使用递归返回值这种方法。

从递归三要素来考虑,本题采用后序遍历:

  • 递归参数与返回值:递归的参数就是根节点、以及两个树节点。而递归的返回值是可以层层向上传递的,我们可以设置为set,代表当前节点的左右子树中包含p、q中的哪个节点。
  • 递归的出口:当node为null的时候,返回空set即可
  • 递归逻辑:
    • 获得左、右节点所具有的孩子节点
    • 创建一个新set
    • 如果当前节点是p、q中的一个则将当前节点放入set
    • 将当前set与左右节点返回的set合并
    • 如果合并之后set中同时包含p、q则说明该节点为最近的公共祖先,将其赋值给类字段
    • 否则返回set

代码如下:

class Solution {TreeNode result = null;boolean first = true;public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {findTree(root,p.val,q.val);return result;}public Set<Integer> findTree(TreeNode node,Integer p,Integer q){if(node == null) return new HashSet<Integer>();Set<Integer> left =  findTree(node.left,p,q);Set<Integer> right =  findTree(node.right,p,q);Set<Integer> set = new HashSet<>();if(node.val == p) set.add(p);else if(node.val == q) set.add(q);set.addAll(left);set.addAll(right);if(set.contains(p) && set.contains(q) && first) {result = node;first = false;}return set;}
}

上面这种算法的核心逻辑就是:只要该节点的左右子树中包含p、q中的任意一个就向上传递,当某一节点凑齐p、q那么就说明该节点是p、q最近的公共祖先。

当然上面的算法效率并不高,我们可以根据题意简洁一下算法,将递归的返回值换为boolean,只要子树中包含p或者q就返回true,代码如下:

class Solution {TreeNode result = null;public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {findTree(root,p.val,q.val);return result;}public boolean findTree(TreeNode node,Integer p,Integer q){if(node == null) return false;boolean left =  findTree(node.left,p,q);boolean right =  findTree(node.right,p,q);if(left && right) {result = node;return true;}else if(node.val == p && (left || right)) {result = node;return true;}else if(node.val == q && (left || right)){result = node;return true;}else if(node.val == q || node.val == p) {return true;}return left || right;}
}

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

题目链接:235. 二叉搜索树的最近公共祖先

解题逻辑:

这个题可以直接使用上面的代码,但是效率很低,因为没有使用到二叉搜索树的特性。

在二叉搜索树中要想找到两个节点p、q的最近公共祖先,我们可以从上往下遍历。

  • 如果当前节点数值小于p、q两个节点,那么说明p、q均在该节点的右子树中,继续往右子树中搜索
  • 如果当前节点数值大于p、q两个节点,那么说明p、q均在该节点的左子树中,继续往左子树中搜索
  • 如果当前节点的数值在p、q两个节点之间,那么就说明该节点就为p、q的最近公共节点(此时p、q肯定分别在该节点的左右子树上,不会有更近的,因为如果继续深入寻找,进入任意一边的子树都将失去另一边子树的节点)

代码如下:

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if(root == null) return null;TreeNode left = null;TreeNode right = null;if(root.val > Math.max(p.val,q.val)) left = lowestCommonAncestor(root.left,p,q);else if(root.val < Math.min(p.val,q.val)) right = lowestCommonAncestor(root.right,p,q);else if(root.val >= Math.min(p.val,q.val) && root.val <= Math.max(p.val,q.val)) return root;if(left != null) return left;else if(right != null) return right;return null;}
}

二叉搜索树中的插入操作

题目链接:701. 二叉搜索树中的插入操作

解题逻辑:
若二叉搜索树为空,则直接插入节点。否则若val小于跟节点值,则插入到左子树。相反则插入到右子树。

代码如下:

class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {if(root == null) return new TreeNode(val);if(val < root.val) {TreeNode left = insertIntoBST(root.left,val);root.left = left;}else {TreeNode right = insertIntoBST(root.right,val);root.right = right;}return root;}
}

删除二叉搜索树中的节点

题目链接: 450. 删除二叉搜索树中的节点

删除二叉树中的节点分为三种情况:

  • 若被删除节点是叶子节点,则直接删除
  • 若被删除节点只有一棵子树,则直接让其子树替代位置即可
  • 若被删除节点有两颗子树,则让被删除节点的直接后继(或者直接前驱)替代被删除节点,然后从二叉搜索树中删除这个直接后继(或者直接前驱),这样就转换成了前面两种情况

代码如下:

class Solution {int preNum = Integer.MAX_VALUE;public TreeNode deleteNode(TreeNode root, int key) {if(root == null) return null;TreeNode left = deleteNode(root.left,key);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.left == null && root.right != null) return root.right;else if(root.left != null && root.right != null) {int rem = preNum;TreeNode node = deleteNode(root,rem);node.val = rem;preNum = rem;return node;}}preNum = root.val;TreeNode right = deleteNode(root.right,key);root.left = left;root.right = right;return root;}
}

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

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

相关文章

Vue插件与组件核心区别详解

在 Vue 中&#xff0c;插件&#xff08;Plugin&#xff09; 和 组件&#xff08;Component&#xff09; 是两种不同层次的概念&#xff0c;它们的主要区别如下&#xff1a;1. 组件 (Component) 定义&#xff1a; Vue 应用的基本构建单元&#xff0c;是可复用的 Vue 实例&#x…

基础NLP | 02 深度学习基本原理

文章目录 深度学习基本原理 数学基础 线代 numpy 常用操作 导数, 梯度 梯度下降法 梯度下降代码 GradientDescent.py 反向传播 完整的反向传播过程 权重更新方式 pytorch 网络结构 全连接层 (线性层) 例子 - 手动实现模拟一个线性层 DNNforward.py 激活函数 激活函数-Sigmoid…

MySQL面试题及详细答案 155道(001-020)

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

Ansible安装与入门

目录 Ansible ansible任务执行模式 ansible执行流程 ansible命令执行过程&#xff08;背会&#xff09; ansible的安装方式 ansible的程序结构&#xff08;yum安装为例&#xff09; ansible的配置文件查找顺序&#xff08;背会&#xff09; 核心配置文件 ansible的配置…

【Spring】Spring Boot启动过程源码解析

目录 一、启动入口 二、SpringApplication的构造过程 2.1 设置应用类型 2.2 设置初始化器&#xff08;Initializer&#xff09; 2.2.1 获取BootstrapRegistryInitializer对象 2.2.2 获取ApplicationContextInitializer对象 2.3 设置监听器&#xff08;Listener&#xff…

CDN架构全景图

CDN架构全景图 CDN&#xff08;内容分发网络&#xff09;是一种通过在全球范围内部署边缘节点服务器&#xff0c;将内容缓存至离用户最近的位置&#xff0c;从而加速内容分发、降低延迟并减轻源站压力的分布式网络架构。其核心设计目标是优化互联网内容传输效率&#xff0c;提升…

【pytest高阶】源码的走读方法及插件hook

一、pytest源码走读方法 依赖库认知篇 &#x1f4e6;这是理解 pytest 源码的 “前菜”&#xff0c;先认识 3 个超重要的小伙伴&#xff1a;iniconfig &#x1f4c4;&#xff1a;像个 “文件小管家”&#xff0c;专门负责读取 ini 配置文件&#xff08;比如 pytest 的配置&#…

算法训练营day32 动态规划理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

今天开始动态规划的部分&#xff01; 其实说白了&#xff0c;动态规划我感觉就是找类似递归的规律&#xff0c; 动态规划理论基础 动态规划&#xff0c;英文&#xff1a;Dynamic Programming&#xff0c;简称DP&#xff0c;如果某一问题有很多重叠子问题&#xff0c;使用动态规…

基于神经网络的手写数字识别系统

基于神经网络的手写数字识别系统 结合模板匹配和神经网络两种方法进行手写数字识别。这个系统包括图像预处理、特征提取、神经网络训练和可视化分析。 %% 基于神经网络的手写数字识别系统%% 清理工作区 clear; clc; close all;%% 加载手写数字数据集 % 使用MATLAB自带的手写数字…

机器学习?一文看懂这门热门技术

&#x1f31f; 什么是机器学习&#xff1f;一文看懂这门热门技术在人工智能&#xff08;AI&#xff09;的大潮中&#xff0c;机器学习&#xff08;Machine Learning, ML&#xff09; 无疑是最耀眼的明星之一。它让计算机具备了 “自我学习” 的能力&#xff0c;让自动驾驶、智能…

Spring的初始化钩子

1. PostConstruct JSR-250 标准注解&#xff08;不是 Spring 独有&#xff09;&#xff0c;用来标记 Bean 初始化完成后要执行的方法。会在 Bean 的构造方法执行完、依赖注入完成后执行。 使用实例&#xff1a; Component public class Demo {PostConstructpublic void init() …

【AI】Java生态对接大语言模型:主流框架深度解析

文章目录1. Deep Java Library (DJL)2. LangChain4j&#xff08;LLM&#xff09;3. HuggingFace Inference API4. OpenAI Java Client技术对比矩阵架构设计建议在人工智能浪潮下&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为技术核心。Java生态通过以下框架实现高效…

【06】C#入门到精通——C# 多个 .cs文件项目 同一项目下添加多个 .cs文件

文章目录1 单个 .cs文件2 创建 多个 .cs文件2.1 添加Hero类2.1 添加ShowInfo类2.3 关于命名空间的引用2.4 所有.cs文件代码3 test3项目文件下载1 单个 .cs文件 上一讲中 描述游戏中英雄的角色 所有代码在一个.cs文件中&#xff0c; 如果代码很多&#xff0c;类很多&#xff0…

【MySQL基础篇】:MySQL常用数据类型的选择逻辑与正确使用

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;MySQL篇–CSDN博客 文章目录数据类型1.数据类型分类2.数值类型int整形类型bit位类型float小…

三、搭建springCloudAlibaba2021.1版本分布式微服务-springcloud loadbalancer负载均衡

什么是负责均衡 Spring Cloud LoadBalancer是一个客户端负载均衡器&#xff0c;类似于Ribbon&#xff0c;但是由于Ribbon已经进入维护模式&#xff0c;并且Ribbon 2并不与Ribbon 1相互兼容&#xff0c;所以Spring Cloud全家桶在Spring Cloud Commons项目中&#xff0c;添加了Sp…

Oracle不完全恢复实战指南:从原理到操作详解

核心提示&#xff1a;当误删表、日志损坏或控制文件丢失时&#xff0c;Oracle的不完全恢复是DBA最后的救命稻草。掌握关键恢复技术&#xff0c;可在数据灾难中力挽狂澜。一、不完全恢复核心概念 1. 核心特点 必须关闭数据库&#xff1a;在MOUNT状态下执行重做日志恢复权限要求&…

Linux之shell脚本篇(二)

一、shell编程之if语句引言Linux在shell编程中&#xff0c;通常都是以自上而下运行&#xff0c;但是为了提高其代码严谨性&#xff0c;我们即引入了多条件 控制语句例如&#xff1a;if、for、while、case等语句&#xff0c;有时候针对条件我们还会结合正则表达式去运用。将这些…

如何在android framewrok dump camera data

实现dump 函数 实现1 void dumpBufferToFile(buffer_handle_t* buffer, int width, int height, int frameNum) {void* data NULL;GraphicBufferMapper::getInstance().lock(*buffer, GRALLOC_USAGE_SW_READ_OFTEN, Rect(width, height), &data);char filename[128];sprin…

机器学习中的可解释性:深入理解SHAP值及其应用

机器学习可解释性的重要性在人工智能技术快速发展的2025年&#xff0c;机器学习模型已经深度渗透到医疗诊断、金融风控、司法量刑等关键领域。然而&#xff0c;随着模型复杂度的不断提升&#xff0c;一个根本性矛盾日益凸显&#xff1a;模型预测性能的提升往往以牺牲可解释性为…

.NET9 使用 OData 协议项目实战

.NET 中 ODate 协议介绍 OData(Open Data Protocol) 是一个开放的 Web 协议&#xff0c;用于查询和更新数据。在 .NET 生态系统中&#xff0c;OData 被广泛支持和使用。 主要特性 1. 统一的数据访问方式 提供标准化的查询语法支持 CRUD 操作支持元数据描述 2. 查询能力 标…