LeetCode530. 二叉搜索树的最小绝对差

news2024/11/24 9:52:03

530. 二叉搜索树的最小绝对差

文章目录

      • [530. 二叉搜索树的最小绝对差](https://leetcode.cn/problems/minimum-absolute-difference-in-bst/)
        • 一、题目
        • 二、题解
          • 方法一:中序遍历递归
          • 方法二:迭代


一、题目

给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

示例 1:

img

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

示例 2:

img

输入:root = [1,0,48,null,null,12,49]
输出:1

提示:

  • 树中节点的数目范围是 [2, 104]
  • 0 <= Node.val <= 105

**注意:**本题与 783 https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/ 相同

二、题解

方法一:中序遍历递归

二叉搜索树(BST)是一种特殊的二叉树,其中每个节点的值大于其左子树中的任何节点的值,且小于其右子树中的任何节点的值。由于这个特性,我们可以通过中序遍历BST来获得一个递增的节点值序列。

题目要求计算树中任意两个不同节点值之间的最小差值,我们可以利用中序遍历得到有序的节点值序列,然后在有序序列中找出相邻节点值之间的最小差值。

算法思路:

  1. 初始化一个全局变量 pre,用于在中序遍历中保存前一个节点的值。
  2. 定义一个辅助函数 getMinDiff,该函数用于中序遍历二叉搜索树并计算最小差值。
  3. getMinDiff 函数中,首先递归遍历左子树。
  4. 在遍历当前节点时,计算当前节点值与 pre 节点值的差的绝对值,并将其与之前计算的最小差值比较,更新最小差值。
  5. pre 更新为当前节点。
  6. 最后递归遍历右子树。
  7. 在主函数 getMinimumDifference 中,初始化一个变量 minv 为整型最大值。
  8. minv 的地址传递给 getMinDiff 函数,以便在中序遍历过程中更新最小差值。
  9. 返回最终计算得到的最小差值。

具体实现:

class Solution {
public:
    TreeNode* pre = nullptr; // 用于保存前一个节点
    void getMinDiff(TreeNode* root, int* MinDiff) {
        if (root == nullptr) return;
        getMinDiff(root->left, MinDiff);
        if (pre && fabs(pre->val - root->val) < *MinDiff) {
            *MinDiff = abs(pre->val - root->val);
        }
        pre = root;
        getMinDiff(root->right, MinDiff);
    }
    
    int getMinimumDifference(TreeNode* root) {
        int minv = INT_MAX; // 初始化最小差值为整型最大值
        int* min = &minv; // 获取最小差值的地址
        getMinDiff(root, min); // 调用辅助函数计算最小差值
        return *min; // 返回最小差值
    }
};

算法分析:

  • 时间复杂度:由于我们对每个节点都只访问了一次,且对每个节点的操作是常数时间的,所以整体时间复杂度为 O(N),其中 N 是节点的总数。
  • 空间复杂度:递归过程中使用的空间主要是函数调用栈,最坏情况下需要 O(H) 的空间,其中 H 是树的高度。在平衡二叉搜索树中,H 的平均值为 O(log N),但在最坏情况下可能达到 O(N)。此外,我们还使用了一个常数大小的额外空间来保存 pre 节点。因此,总的空间复杂度为 O(H) 到 O(N)。

当然,还有更方便的写法

class Solution {
public:
    TreeNode* pre = nullptr;
    int minv = INT_MAX;
    void getMinDiff(TreeNode* root) {
        if (root == nullptr) return;
        getMinDiff(root->left);
        if (pre){
            minv = min(abs(pre->val - root->val),minv);
        }
        pre = root;
        getMinDiff(root->right);
    }
    int getMinimumDifference(TreeNode* root) {
        getMinDiff(root);
        return minv;
    }
};
方法二:迭代

算法思路

  • 进行中序遍历,获取有序的节点值序列。
  • 在有序序列中找到相邻节点值之间的最小差值。

具体实现

  • 我们使用栈来进行中序遍历。
  • 初始化栈,当前节点指针 cur 指向根节点,前一个节点指针 pre 初始为 nullptr
  • 初始化一个变量 result 用于记录最小差值,初始值为整型最大值 INT_MAX
  • 进入循环,只要栈不为空或者当前节点不为空:
    • 如果当前节点存在(非空),则将当前节点入栈,并将当前节点指针移动到左子节点,以获取最左边的节点(最小值)。
    • 如果当前节点不存在,说明已经到达了最左边的节点,此时从栈中弹出节点,并进行如下操作:
      • 计算当前节点值与前一个节点值的差,更新 result
      • 更新前一个节点指针 pre 为当前节点。
      • 将当前节点指针移动到右子节点,继续处理右子树。
  • 循环结束后,返回 result 作为结果。
/**
 * 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:
    int getMinimumDifference(TreeNode* root) {
        stack<TreeNode*> st;
        if(root == nullptr) return 0;
        TreeNode *cur = root;
        TreeNode *pre = nullptr;
        int result = INT_MAX;
        while(!st.empty() || cur!= NULL){
            if(cur){
                st.push(cur);
                cur = cur->left;
            }else{
                cur = st.top();
                st.pop();
                if(pre){
                    result = min(cur->val-pre->val, result);
                } 
                pre = cur;
                cur = cur->right;
            }
        }
        return result;
    }
};

算法分析:

  • 时间复杂度:中序遍历需要访问每个节点一次,所以时间复杂度是 O(n),其中 n 是节点数量。
  • 空间复杂度:使用了一个栈来存储节点,所以空间复杂度是 O(h),其中 h 是树的高度。在最坏情况下,树是一条链,h 为 n,但通常情况下 h 远小于 n。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一篇打通,pytest自动化测试框架详细,从0到1精通实战(一)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 pytest单元测试框…

js设置css变量控制页面一行展示指定个数的元素

前置知识&#xff1a; CSS变量之var()函数的应用——动态修改样式 & root的使用 flex相关知识 场景&#xff1a; 动态设置给父元素内子元素设置每行排列几个 通过 document.body.style.setProperty(--itemNum, 5)设置样式变量&#xff0c;然后通过给父元素设置display: f…

此芯科技加入 openKylin 开源社区

导读近日消息&#xff0c;据此芯科技官方公众号表示&#xff0c;此芯科技目前已经签署 openKylin 社区 CLA&#xff08;Contributor License Agreement 贡献者许可协议&#xff09;&#xff0c;正式加入 openKylin 开源社区。 此芯科技成立于 2021 年&#xff0c;是一家专注于设…

EDUSRC之一次奇葩的文件上传

当时误打误撞发现的&#xff0c;觉得挺奇葩的&#xff0c;记录下 一个正常的图片上传的点&#xff0c;文件类型白名单 但是比较巧的是当时刚对上面的id进行过注入测试&#xff0c;有一些遗留的测试 payload 没删&#xff0c;然后在测试上传的时候就发现.php的后缀可以上传了&a…

Https、CA证书、数字签名

Https Http协议 Http协议是目前应用比较多应用层协议&#xff0c;浏览器对于Http协议已经实现。Http协议基本的构成部分有 请求行 &#xff1a; 请求报文的第一行请求头 &#xff1a; 从第二行开始为请求头内容的开始部分。每一个请求头都是由K-V键值对组成。请求体&#xf…

Remote Sensing,2023 | 基于SBL的分布式毫米波相干雷达成像的高效实现

Remote Sensing,2023 | 基于SBL的分布式毫米波相干雷达成像的高效实现 注1&#xff1a;本文系“无线感知论文速递”系列之一&#xff0c;致力于简洁清晰完整地介绍、解读无线感知领域最新的顶会/顶刊论文(包括但不限于 Nature/Science及其子刊; MobiCom, Sigcom, MobiSys, NSDI…

Kubeadm安装K8s集群

一、硬件环境 准备3台Linux服务器&#xff0c;此处用Vmware虚拟机。 主机名CPU内存k8smaster2核4Gk8snode12核4Gk8snode22核4G 二、系统前置准备 配置三台主机的hosts文件 cat << EOF > /etc/hosts 192.168.240.130 k8smaster 192.168.240.132 k8snode1 192.168.…

小白必看:测试人有必要参考的软件测试工作规范

为了规范测试工作、减少开发与测试之前的沟通成本、保证项目进度、提高软件质量&#xff0c;测试人员有必要参考这份软件测试工作规范。 1.1. 编码规范 软件程序开发需要遵守编码规范&#xff0c;一是可以减少代码的维护成本&#xff0c;提高开发工作效率&#xff1b;二是有…

2023国赛数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …

AOPSpringAOP两种动态代理

1、什么是AOP 切面编程&#xff08;Aspect-Oriented Programming&#xff0c;AOP&#xff09;是一种软件开发方法&#xff0c;旨在通过分离关注点&#xff08;Concerns&#xff09;来增强代码的模块性、可维护性和可重用性。 AOP 是 OOP 的延续&#xff0c;是软件开发中的一个…

【Qt高阶】老Qt都不一定清楚的“QObject线程亲和性”【2023.08.13】

老Qt都不一定清楚的“线程亲和性” 与题目无关 感觉自己还挺2&#xff0c;有粉丝点了那个契约者会给up发个鼓励的话&#xff0c;我还以为是人私信发的&#xff0c;都挨个感谢了&#xff0c;后来才意识到是系统自动发的&#x1f623;&#x1f623;&#x1f623;。 自上上期视频对…

⛳ Java集合框架

目录 ⛳ Java集合框架&#x1f3a8; 一、概述&#x1f3ed; 二、Iterator接口&#x1f4ad; 2.1、基础用法&#x1f69c; 2.2、原理&#x1f43e; 2.3、为什么需要iterator接口☁ 2.4、ListIterator接口&#x1f4e2; 2.5、iterator在集合中的实现例子2.5.1、Iterator在ArrayLi…

潜水减压多普勒超声气泡信号识别方法

用三参量模糊分析法识别潜水减压气泡信号的研究 摘要 三参量模糊分析法。建立了 f-p-Δp( 频率、谱峰、峰差) 三参量模糊分析法&#xff0c;综合气泡原本特征以及背景噪声计算评分以识别气泡&#xff0c;最后给予 SPENCERⅠ &#xff5e; Ⅲ分级原理和方法 减压气泡信号的能量…

分布式 - 消息队列Kafka:Kafka生产者发送消息的方式

文章目录 1. Kafka 生产者2. kafaka 命令行操作3. kafka 生产者发送消息流程4. Kafka 生产者的创建5. Kafka 生产者发送消息1. 发送即忘记2. 同步发送3. 异步发送 6. Kafka 消息对象 ProducerRecord 1. Kafka 生产者 不管是把Kafka作为消息队列、消息总线还是数据存储平台&…

Vue3组件库

Vue3组件库 ViteVue3TypescriptTSX 1、项目搭建 1.1、创建项目&#xff08;yarn&#xff09; D:\WebstromProject>yarn create vite yarn create v1.22.19 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh p…

asyncio是什么?

如果把进程比作从A处到B处去这件事&#xff0c;那么线程就是可供选择的多条道路&#xff0c;协程就是道路上特殊路段&#xff08;类似限速&#xff0c;一整条道路都是特殊路段的话&#xff0c;就是全部由协程实现&#xff09; 例图如下&#xff1a; 1. 什么是协程&#xff08…

FPGA应用学习笔记----CORDIC 算法和小结

加减移位操作来运算三角函数&#xff0c;开根号&#xff0c;求对数 圆周旋转模式

沁恒ch32V208处理器开发(四)串口通信

目录 串口资源资源配置同步模式单线半双工模式中断DMA 串口的初始化串口通信的实现 串口资源 资源配置 CH32V208 系列&#xff0c;是基于 RISC-V 指令架构设计的 32 位 RISC 内核 MCU&#xff0c;根据封装的不同&#xff0c;可用的USART串口资源如下表所示&#xff1a; 且US…

完美解决Github提交PR后报错:File is not gofumpt-ed (gofumpt)

问题阐述 最近在Github上提交PR后&#xff0c;遇到了这么一个问题&#xff1a;golangci-lint运行失败&#xff0c;具体原因是File is not gofumpt-ed (gofumpt)。 名词解释 golangci-lint&#xff1a; golangci-lint 是Go语言社区中常用的代码质量检查工具&#xff0c;它可以…