二叉搜索树题目:将有序数组转换为二叉搜索树

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 证明
    • 代码
    • 复杂度分析

题目

标题和出处

标题:将有序数组转换为二叉搜索树

出处:108. 将有序数组转换为二叉搜索树

难度

4 级

题目描述

要求

给定整数数组 nums \texttt{nums} nums,其中元素已经按升序排列,将其转换为高度平衡二叉搜索树。

高度平衡二叉树满足每个结点的左右子树的高度差的绝对值不超过 1 \texttt{1} 1

示例

示例 1:

示例 1.1

输入: nums   =   [-10,-3,0,5,9] \texttt{nums = [-10,-3,0,5,9]} nums = [-10,-3,0,5,9]
输出: [0,-3,9,-10,null,5] \texttt{[0,-3,9,-10,null,5]} [0,-3,9,-10,null,5]
解释: [0,-10,5,null,-3,null,9] \texttt{[0,-10,5,null,-3,null,9]} [0,-10,5,null,-3,null,9] 也将被视为正确答案:

示例 1.2

示例 2:

示例 2

输入: nums   =   [1,3] \texttt{nums = [1,3]} nums = [1,3]
输出: [3,1] \texttt{[3,1]} [3,1]
解释: [1,null,3] \texttt{[1,null,3]} [1,null,3] [3,1] \texttt{[3,1]} [3,1] 都是高度平衡二叉搜索树。

数据范围

  • 1 ≤ nums.length ≤ 10 4 \texttt{1} \le \texttt{nums.length} \le \texttt{10}^\texttt{4} 1nums.length104
  • -10 4 ≤ nums[i] ≤ 10 4 \texttt{-10}^\texttt{4} \le \texttt{nums[i]} \le \texttt{10}^\texttt{4} -104nums[i]104
  • nums \texttt{nums} nums严格递增顺序排列

解法

思路和算法

由于二叉搜索树的中序遍历序列是单调递增的,因此给定的升序数组即为二叉搜索树的中序遍历序列。在只有中序遍历序列的情况下,无法唯一地确定二叉搜索树。

为了得到高度平衡二叉搜索树,构造的二叉搜索树应满足根结点的左子树和右子树的结点数尽可能接近。当结点总数是奇数时,根结点值应为中序遍历序列的中间位置的结点值,根结点的左子树和右子树的结点数应相等;当结点总数是偶数时,根结点值应为中序遍历序列的中间位置的两个结点值之一,根结点的左子树和右子树的结点数之差的绝对值应等于 1 1 1

确定高度平衡二叉搜索树的根结点之后,其余的结点值分别位于根结点的左子树和右子树中,数组中位于根结点左侧的值都在左子树中,数组中位于根结点右侧的值都在右子树中,左子树和右子树也是高度平衡二叉搜索树。可以通过数学归纳法证明,如果两个高度平衡二叉搜索树的结点数之差的绝对值不超过 1 1 1,则这两个高度平衡二叉搜索树的高度之差的绝对值不超过 1 1 1

由于高度平衡二叉搜索树的每个子树也都是高度平衡二叉搜索树,每个子树包含的结点值的集合对应给定的数组中的连续子数组,因此可以使用递归的方式构造高度平衡二叉搜索树,递归的过程中只要指定每个子树包含的结点值的集合对应的连续子数组的下标区间 [ start , end ] [\textit{start}, \textit{end}] [start,end] 即可。

递归的终止条件是下标区间为空,即 start > end \textit{start} > \textit{end} start>end,此时对应的子树为空。对于其余情况,首先根据 start \textit{start} start end \textit{end} end 计算得到根结点值的下标 mid \textit{mid} mid 并使用该结点值创建根结点,然后分别使用下标区间 [ start , mid − 1 ] [\textit{start}, \textit{mid} - 1] [start,mid1] [ mid + 1 , end ] [\textit{mid} + 1, \textit{end}] [mid+1,end] 创建根结点的左子树和右子树。

start ≤ end \textit{start} \le \textit{end} startend 时, mid \textit{mid} mid 的取值的唯一性取决于下标区间 [ start , end ] [\textit{start}, \textit{end}] [start,end] 内的元素个数的奇偶性。如果下标区间 [ start , end ] [\textit{start}, \textit{end}] [start,end] 内的元素个数是奇数,则 mid \textit{mid} mid 的取值是唯一的;如果下标区间 [ start , end ] [\textit{start}, \textit{end}] [start,end] 内的元素个数是偶数,则 mid \textit{mid} mid 的取值是不唯一的,可以是中间位置左边的下标或者中间位置右边的下标。

  • mid = ⌊ start + end 2 ⌋ \textit{mid} = \Big\lfloor \dfrac{\textit{start} + \textit{end}}{2} \Big\rfloor mid=2start+end 时, mid \textit{mid} mid 是中间位置左边的下标。

  • mid = ⌊ start + end + 1 2 ⌋ \textit{mid} = \Big\lfloor \dfrac{\textit{start} + \textit{end} + 1}{2} \Big\rfloor mid=2start+end+1 时, mid \textit{mid} mid 是中间位置右边的下标。

如果下标区间 [ start , end ] [\textit{start}, \textit{end}] [start,end] 内的元素个数是奇数,则上述两种方法计算得到的 mid \textit{mid} mid 的值相同。

由此可以得到三种构造高度平衡二叉搜索树的方法。

  • 每次都将根结点值取为中间位置左边的下标处的值。

  • 每次都将根结点值取为中间位置右边的下标处的值。

  • 每次随机将根结点值取为中间位置左边或右边的下标处的值。

证明

为了证明上述构造高度平衡二叉搜索树的方法的正确性,需要证明:如果两个高度平衡二叉搜索树的结点数之差的绝对值不超过 1 1 1,则这两个高度平衡二叉搜索树的高度之差的绝对值不超过 1 1 1

h ( n ) h(n) h(n) 表示有 n n n 个结点的高度平衡二叉搜索树的高度,其中 n ≥ 1 n \ge 1 n1,规定 h ( 1 ) = 0 h(1) = 0 h(1)=0 h ( 2 ) = h ( 3 ) = 1 h(2) = h(3) = 1 h(2)=h(3)=1,则对于 1 ≤ n ≤ 3 1 \le n \le 3 1n3 h ( n ) = ⌊ log ⁡ n ⌋ h(n) = \lfloor \log n \rfloor h(n)=logn

n ≥ 4 n \ge 4 n4 时,假设对于任意 1 ≤ m < n 1 \le m < n 1m<n 都有 h ( m ) = ⌊ log ⁡ m ⌋ h(m) = \lfloor \log m \rfloor h(m)=logm,需要证明 h ( n ) = ⌊ log ⁡ n ⌋ h(n) = \lfloor \log n \rfloor h(n)=logn

  • n n n 是奇数时,令 n = 2 k + 1 n = 2k + 1 n=2k+1,其中 k ≥ 1 k \ge 1 k1,则根结点的左子树和右子树各有 k k k 个结点。由于 k < n k < n k<n,因此 h ( k ) = ⌊ log ⁡ k ⌋ h(k) = \lfloor \log k \rfloor h(k)=logk 已知,此时 h ( n ) = h ( k ) + 1 = ⌊ log ⁡ k ⌋ + 1 h(n) = h(k) + 1 = \lfloor \log k \rfloor + 1 h(n)=h(k)+1=logk+1。由于 n = 2 k + 1 n = 2k + 1 n=2k+1,因此 n − 1 = 2 k n - 1 = 2k n1=2k log ⁡ ( n − 1 ) = log ⁡ 2 k = log ⁡ k + 1 \log (n - 1) = \log 2k = \log k + 1 log(n1)=log2k=logk+1,取整得 ⌊ log ⁡ ( n − 1 ) ⌋ = ⌊ log ⁡ k ⌋ + 1 \lfloor \log (n - 1) \rfloor = \lfloor \log k \rfloor + 1 log(n1)⌋=logk+1。由于 n n n 是奇数,因此 ⌊ log ⁡ n ⌋ = ⌊ log ⁡ ( n − 1 ) ⌋ \lfloor \log n \rfloor = \lfloor \log (n - 1) \rfloor logn=log(n1)⌋ ⌊ log ⁡ n ⌋ = ⌊ log ⁡ k ⌋ + 1 \lfloor \log n \rfloor = \lfloor \log k \rfloor + 1 logn=logk+1 h ( n ) = ⌊ log ⁡ n ⌋ h(n) = \lfloor \log n \rfloor h(n)=logn

  • n n n 是偶数时,令 n = 2 k + 2 n = 2k + 2 n=2k+2,其中 k ≥ 1 k \ge 1 k1,则根结点的左子树和右子树分别有 k k k 个结点和 k + 1 k + 1 k+1 个结点。由于 k + 1 < n k + 1 < n k+1<n,因此 h ( k + 1 ) = ⌊ log ⁡ ( k + 1 ) ⌋ h(k + 1) = \lfloor \log (k + 1) \rfloor h(k+1)=log(k+1)⌋ 已知,此时 h ( n ) = h ( k + 1 ) + 1 = ⌊ log ⁡ ( k + 1 ) ⌋ + 1 h(n) = h(k + 1) + 1 = \lfloor \log (k + 1) \rfloor + 1 h(n)=h(k+1)+1=log(k+1)⌋+1。由于 n = 2 k + 2 = 2 ( k + 1 ) n = 2k + 2 = 2(k + 1) n=2k+2=2(k+1),因此 log ⁡ n = log ⁡ 2 ( k + 1 ) = log ⁡ ( k + 1 ) + 1 \log n = \log 2(k + 1) = \log (k + 1) + 1 logn=log2(k+1)=log(k+1)+1,取整得 ⌊ log ⁡ n ⌋ = ⌊ log ⁡ ( k + 1 ) ⌋ + 1 \lfloor \log n \rfloor = \lfloor \log (k + 1) \rfloor + 1 logn=log(k+1)⌋+1 h ( n ) = ⌊ log ⁡ n ⌋ h(n) = \lfloor \log n \rfloor h(n)=logn

因此对于任意正整数 n n n,都有 h ( n ) = ⌊ log ⁡ n ⌋ h(n) = \lfloor \log n \rfloor h(n)=logn。由于任意两个相邻正整数的对数之差一定不超过 1 1 1,因此当 n ≥ 2 n \ge 2 n2 时,一定有 h ( n ) − h ( n − 1 ) ≤ 1 h(n) - h(n - 1) \le 1 h(n)h(n1)1

代码

下面的代码为每次都将根结点值取为中间位置左边的下标处的值的做法。

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return createBST(nums, 0, nums.length - 1);
    }

    public TreeNode createBST(int[] nums, int start, int end) {
        if (start > end) {
            return null;
        }
        int mid = (end - start) / 2 + start;
        return new TreeNode(nums[mid], createBST(nums, start, mid - 1), createBST(nums, mid + 1, end));
    }
}

下面的代码为每次都将根结点值取为中间位置右边的下标处的值的做法。

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return createBST(nums, 0, nums.length - 1);
    }

    public TreeNode createBST(int[] nums, int start, int end) {
        if (start > end) {
            return null;
        }
        int mid = (end - start + 1) / 2 + start;
        return new TreeNode(nums[mid], createBST(nums, start, mid - 1), createBST(nums, mid + 1, end));
    }
}

下面的代码为每次随机将根结点值取为中间位置左边或右边的下标处的值的做法。

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
        return createBST(nums, 0, nums.length - 1);
    }

    public TreeNode createBST(int[] nums, int start, int end) {
        if (start > end) {
            return null;
        }
        int mid = (end - start + (int) (Math.random() * 2)) / 2 + start;
        return new TreeNode(nums[mid], createBST(nums, start, mid - 1), createBST(nums, mid + 1, end));
    }
}

复杂度分析

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。每个元素都被访问一次。

  • 空间复杂度: O ( log ⁡ n ) O(\log n) O(logn),其中 n n n 是数组 nums \textit{nums} nums 的长度。空间复杂度主要是递归调用的栈空间,由于构造的是高度平衡二叉搜索树,因此递归调用栈的深度是 O ( log ⁡ n ) O(\log n) O(logn)。注意返回值不计入空间复杂度。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大辩论:人工智能时代人类和软件的未来

关于人工智能将在多大程度上接管软件开发、交付和支持任务及其对就业的影响&#xff0c;聆听双方的争论&#xff0c;对于技术来说既令人兴奋&#xff0c;又让人类感到恐惧。争论是这样的&#xff1a; 人工智能倡导者&#xff1a;欢迎来到未来&#xff01;凭借当今人工智能的能…

猫挑食不吃猫粮怎么办?可以解决猫咪挑食的主食冻干推荐

现在的猫奴们普遍将自家的小猫视为掌上明珠&#xff0c;宠爱有加。然而&#xff0c;这种宠爱有时也会导致猫咪养成一些不良习惯&#xff0c;比如挑食。猫挑食不吃猫粮怎么办&#xff1f;今天为大家分享一个既不让咱宝贝猫咪受罪又可以改善猫咪挑食的方法。 一、猫咪是为什么挑食…

(C语言)qsort函数详解

目录 1. qsort解释 2. qsort实例 2.1 qsort排列整形数组类型&#xff1a; 2.2 qsort排列结构体类型数据&#xff08;字符串&#xff09;&#xff1a; 2.3 qsort排列结构体类型数据&#xff08;整形&#xff09;&#xff1a; 1. qsort解释 我们可以进入网站&#xff1a;qso…

第一天 走进Docker的世界

第一天 走进Docker的世界 介绍docker的前世今生&#xff0c;了解docker的实现原理&#xff0c;以Django项目为例&#xff0c;带大家如何编写最佳的Dockerfile构建镜像。通过本章的学习&#xff0c;大家会知道docker的概念及基本操作&#xff0c;并学会构建自己的业务镜像&…

王者荣耀整蛊搭建直播新玩法/obs贴纸配置教程

最近很火的王者荣耀整蛊直播&#xff0c;相信很多玩王者的玩家也想开一个直播&#xff0c;但是看到这种直播娱乐效果很有意思也想搭建一个&#xff0c;这里梦哥给大家出了一期搭建的教程&#xff01; 进阶版视频教程&#xff1a; 这期的教程是进阶版新玩法升级&#xff0c;具体…

DataGrip 2023:让数据库开发变得更简单、更高效 mac/win

JetBrains DataGrip 2023是一款功能强大的数据库IDE&#xff0c;专为数据库开发和管理而设计。通过DataGrip&#xff0c;您可以连接到各种关系型数据库管理系统(RDBMS)&#xff0c;并使用其提供的一组工具来查询、管理、编辑和开发数据库。 DataGrip 2023软件获取 DataGrip 2…

前端面试 跨域理解

2 实现 2-1 JSONP 实现 2-2 nginx 配置 2-2 vue 开发中 webpack自带跨域 2 -3 下载CORS 插件 或 chrome浏览器配置跨域 2-4 通过iframe 如&#xff1a;aaa.com 中读取bbb.com的localStorage 1)在aaa.com的页面中&#xff0c;在页面中嵌入一个src为bbb.com的iframe&#x…

大模型理论基础(so-large-lm)课程笔记!

Datawhale干货 作者&#xff1a;辣条&#xff0c;Datawhale优秀学习者 前 言 在当前信息时代&#xff0c;大型语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;的发展速度和影响力日益显著。随着技术进步&#xff0c;我们见证了从基本的Transformer架构…

【三维重建】【SLAM】SplaTAM:基于3D高斯的密集RGB-D SLAM(CVPR 2024)

题目&#xff1a;SplaTAM: Splat, Track & Map 3D Gaussians for Dense RGB-D SLAM 地址&#xff1a;spla-tam.github.io 机构&#xff1a;CMU&#xff08;卡内基梅隆大学&#xff09;、MIT&#xff08;美国麻省理工&#xff09; 总结&#xff1a;SplaTAM&#xff0c;一个新…

在你的 Vue + Electron 项目里,引入 ESLint

因为我的项目是基于 Electron 平台的 Web 应用&#xff0c;使用 Vue 3 实现&#xff0c;而且用了 TypeScript&#xff0c;所以&#xff0c;在引入 ESLint 的时候&#xff0c;要考虑好几种规范的问题。 文章目录 零、简介1. 规则2. 配置文件3. 共享配置4. 插件5. 解析器6. 自定义…

【比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据】操作批量新增、分页查询(三)

orm框架使用性能比较 比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据 环境&#xff1a; idea jdk17 spring boot 3.0.7 mysql 8.0测试条件常规对象 orm 框架是否支持xml是否支持 Lambda对比版本mybatis☑️☑️3.5.4sqltoy☑️☑️5.2.98lazy✖️☑️1.2.4…

哪个有名的工具可以安全记事 私密记事本笔记推荐

在这个数字化的时代&#xff0c;我们的生活已经离不开各种记事工具。它们帮助我们记录生活中的点点滴滴&#xff0c;无论是工作上的重要事项&#xff0c;还是个人的私密心情。然而&#xff0c;当我在寻找一个能够安心记录私密事情的工具时&#xff0c;安全性成为了我最关心的因…

23.基于springboot + vue实现的前后端分离-在线旅游网站系统(项目 + 论文PPT)

项目介绍 本旅游网站系统采用的数据库是MYSQL &#xff0c;使用 JSP 技术开发&#xff0c;在设计过程中&#xff0c;充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。 技术选型 后端: SpringBoot Mybatis 数据库 : MyS…

Matlab 机器人工具箱 动力学

文章目录 R.dynR.fdynR.accelR.rneR.gravloadR.inertiaR.coriolisR.payload参考链接 官网&#xff1a;Robotics Toolbox - Peter Corke R.dyn 查看动力学参数 mdl_puma560; p560.dyn;%查看puma560机械臂所有连杆的动力学参数 p560.dyn(2);%查看puma560机械臂第二连杆的动力学…

MongoDB Java实战

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于MongoDB系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础…

SpringBoot+Vue实现el-table表头筛选排序(附源码)

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;在笑大学牲 &#x1f39f;️个人主页&#xff1a;无所谓^_^ ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 前言 后台系统对table组件的需求是最常见的&#xff0c;不过element-ui的el…

机器学习-面经(part2)

3. 验证方式 3.1什么是过拟合?产生过拟合原因? 定义:指模型在训练集上的效果很好,在测试集上的预测效果很差 数据有噪声 训练数据不足,有限的训练数据 训练模型过度导致模型非常复杂3.2 如何避免过拟合问题? 3.3 什么是机器学习的欠拟合?产生原…

vmware扩容CentOS磁盘的两种方案

vmware扩容CentOS磁盘的两种方案 扩容磁盘的两种需求 扩容磁盘&#xff0c;一种情况&#xff0c;我们希望见原来不足的存储无缝伸缩扩容&#xff0c;通常是给原本的根目录/扩容&#xff0c;另一种是在另一个目录上挂载新磁盘。 本次记录第一种情况&#xff0c;主要参考https…

[LeetBook]【学习日记】寻找链表相交节点

来源于「Krahets」的《图解算法数据结构》 https://leetcode.cn/leetbook/detail/illustration-of-algorithm/ 本题与主站 160 题相同&#xff1a;https://leetcode-cn.com/problems/intersection-of-two-linked-lists/ 训练计划 V 某教练同时带教两位学员&#xff0c;分别以…

Sqli-labs靶场第19关详解[Sqli-labs-less-19]自动化注入-SQLmap工具注入

Sqli-labs-Less-19 通过测试发现&#xff0c;在登录界面没有注入点&#xff0c;通过已知账号密码admin&#xff0c;admin进行登录发现&#xff1a; 返回了Referer &#xff0c;设想如果在Referer 尝试加上注入语句&#xff08;报错注入&#xff09;&#xff0c;测试是否会执行…