当前位置: 首页 > news >正文

[Leetcode] 0108. 将有序数组转换为二叉搜索树

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

题目描述

给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。

高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums严格递增 顺序排列

解法

二叉搜索树的中序遍历是升序序列,题目给定的数组是按照升序排序的有序数组,因此可以确保数组是二叉搜索树的中序遍历序列。

给定二叉搜索树的中序遍历,是否可以唯一地确定二叉搜索树?答案是否定的。如果没有要求二叉搜索树的高度平衡,则任何一个数字都可以作为二叉搜索树的根节点,因此可能的二叉搜索树有多个。img

如果增加一个限制条件,即要求二叉搜索树的高度平衡,是否可以唯一地确定二叉搜索树?答案仍然是否定的。img

直观地看,我们可以选择中间数字作为二叉搜索树的根节点,这样分给左右子树的数字个数相同或只相差 1,可以使得树保持平衡。如果数组长度是奇数,则根节点的选择是唯一的,如果数组长度是偶数,则可以选择中间位置左边的数字作为根节点或者选择中间位置右边的数字作为根节点,选择不同的数字作为根节点则创建的平衡二叉搜索树也是不同的。

img

确定平衡二叉搜索树的根节点之后,其余的数字分别位于平衡二叉搜索树的左子树和右子树中,左子树和右子树分别也是平衡二叉搜索树,因此可以通过递归的方式创建平衡二叉搜索树。

递归的基准情形是平衡二叉搜索树不包含任何数字,此时平衡二叉搜索树为空。

在给定中序遍历序列数组的情况下,每一个子树中的数字在数组中一定是连续的,因此可以通过数组下标范围确定子树包含的数字,下标范围记为 \([\textit{left}, \textit{right}]\)。对于整个中序遍历序列,下标范围从 \(\textit{left}=0\)\(\textit{right}=\textit{nums}.\text{length}-1\)。当 \(\textit{left}>\textit{right}\) 时,平衡二叉搜索树为空。

以下三种方法中,方法一总是选择中间位置左边的数字作为根节点,方法二总是选择中间位置右边的数字作为根节点,方法三是方法一和方法二的结合,选择任意一个中间位置数字作为根节点。

方法一:中序遍历,总是选择中间位置左边的数字作为根节点

选择中间位置左边的数字作为根节点,则根节点的下标为 \(\textit{mid}=(\textit{left}+\textit{right})/2\),此处的除法为整数除法。

时间复杂度:\(O(n)\),其中 \(n\) 是数组的长度。每个数字只访问一次。
空间复杂度:\(O(\log n)\),其中 \(n\) 是数组的长度。空间复杂度不考虑返回值,因此空间复杂度主要取决于递归栈的深度,递归栈的深度是 \(O(\log n)\)

img

Python3

class Solution:def sortedArrayToBST(self, nums: List[int]) -> TreeNode:def helper(left, right):if left > right:return None# 总是选择中间位置左边的数字作为根节点mid = (left + right) // 2root = TreeNode(nums[mid])root.left = helper(left, mid - 1)root.right = helper(mid + 1, right)return rootreturn helper(0, len(nums) - 1)

C++

class Solution {
public:TreeNode* sortedArrayToBST(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}TreeNode* helper(vector<int>& nums, int left, int right) {if (left > right) {return nullptr;}// 总是选择中间位置左边的数字作为根节点int mid = (left + right) / 2;TreeNode* root = new TreeNode(nums[mid]);root->left = helper(nums, left, mid - 1);root->right = helper(nums, mid + 1, right);return root;}
};

方法二:中序遍历,总是选择中间位置右边的数字作为根节点

选择中间位置右边的数字作为根节点,则根节点的下标为 \(\textit{mid}=(\textit{left}+\textit{right}+1)/2\),此处的除法为整数除法。

时间复杂度:\(O(n)\),其中 \(n\) 是数组的长度。每个数字只访问一次。
空间复杂度:\(O(\log n)\),其中 \(n\) 是数组的长度。空间复杂度不考虑返回值,因此空间复杂度主要取决于递归栈的深度,递归栈的深度是 \(O(\log n)\)

img

Python3

class Solution:def sortedArrayToBST(self, nums: List[int]) -> TreeNode:def helper(left, right):if left > right:return None# 总是选择中间位置右边的数字作为根节点mid = (left + right + 1) // 2root = TreeNode(nums[mid])root.left = helper(left, mid - 1)root.right = helper(mid + 1, right)return rootreturn helper(0, len(nums) - 1)

C++

class Solution {
public:TreeNode* sortedArrayToBST(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}TreeNode* helper(vector<int>& nums, int left, int right) {if (left > right) {return nullptr;}// 总是选择中间位置右边的数字作为根节点int mid = (left + right + 1) / 2;TreeNode* root = new TreeNode(nums[mid]);root->left = helper(nums, left, mid - 1);root->right = helper(nums, mid + 1, right);return root;}
};

方法三:中序遍历,选择任意一个中间位置数字作为根节点

选择任意一个中间位置数字作为根节点,则根节点的下标为 \(\textit{mid}=(\textit{left}+\textit{right})/2\)\(\textit{mid}=(\textit{left}+\textit{right}+1)/2\) 两者中随机选择一个,此处的除法为整数除法。

时间复杂度:\(O(n)\),其中 \(n\) 是数组的长度。每个数字只访问一次。
空间复杂度:\(O(\log n)\),其中 \(n\) 是数组的长度。空间复杂度不考虑返回值,因此空间复杂度主要取决于递归栈的深度,递归栈的深度是 \(O(\log n)\)

img

Python3

class Solution:def sortedArrayToBST(self, nums: List[int]) -> TreeNode:def helper(left, right):if left > right:return None# 选择任意一个中间位置数字作为根节点mid = (left + right + randint(0, 1)) // 2root = TreeNode(nums[mid])root.left = helper(left, mid - 1)root.right = helper(mid + 1, right)return rootreturn helper(0, len(nums) - 1)

C++

class Solution {
public:TreeNode* sortedArrayToBST(vector<int>& nums) {return helper(nums, 0, nums.size() - 1);}TreeNode* helper(vector<int>& nums, int left, int right) {if (left > right) {return nullptr;}// 选择任意一个中间位置数字作为根节点int mid = (left + right + rand() % 2) / 2;TreeNode* root = new TreeNode(nums[mid]);root->left = helper(nums, left, mid - 1);root->right = helper(nums, mid + 1, right);return root;}
};

相关文章:

[Leetcode] 0108. 将有序数组转换为二叉搜索树

108. 将有序数组转换为二叉搜索树 题目描述 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1&#xff1a…...

Pandas数据导入和导出:CSV、Excel、MySQL、JSON

导入MySQL查询结果&#xff1a;read_sql import pandascon "mysqlpymysql://user:pass127.0.0.1/test" sql "SELECT * FROM student WHERE id 2"# sql查询 df1 pandas.read_sql(sqlsql, concon) print(df1)导入MySQL整张表&#xff1a;read_sql_table…...

第16期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练 Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…...

省钱兄短剧短视频视频滑动播放模块源码支持微信小程序h5安卓IOS

# 开源说明 开源省钱兄短剧系统的播放视频模块&#xff08;写了测试弄了好久才弄出来、最核心的模块、已经实战了&#xff09;&#xff0c;使用uniapp技术&#xff0c;提供学习使用&#xff0c;支持IOSAndroidH5微信小程序&#xff0c;使用Hbuilder导入即可运行 #注意&#xff…...

SDRAM学习笔记(MT48LC16M16A2,w9812g6kh)

一、基本知识 SDRAM : 即同步动态随机存储器&#xff08;Synchronous Dynamic Random Access Memory&#xff09;, 同步是指其时钟频率与对应控制器&#xff08;CPU/FPGA&#xff09;的系统时钟频率相同&#xff0c;并且内部命令 的发送与数据传输都是以该时钟为基准&#xff…...

ARM 学习笔记3 STM32G4 定时器相关资料整理

官方文档 AN4539 HRTIM cookbookAN4539_HRTIM使用指南 中文版的文档&#xff0c;注意文档的版本号滞后于英文原版ST MCU中文文档 中文文档汇总 博客文章 STM32-定时器详解【STM32H7教程】第63章 STM32H7的高分辨率定时器HRTIM基础知识和HAL库APIstm32f334 HRTIM触发ADC注入中…...

LeetCode 917 仅仅反转字母 简单

题目 - 点击直达 1. XXXXX1. 917 仅仅反转字母 简单1. 原题链接2. 题目要求3. 基础框架 2. 解题思路1. 思路分析2. 时间复杂度3. 代码实现 1. XXXXX 1. 917 仅仅反转字母 简单 给你一个字符串 s &#xff0c;根据下述规则反转字符串&#xff1a; 所有非英文字母保留在原有位置…...

JAVA深化篇_25—— IO流章节全网最全总结(附详细思维导图)

IO流章节全网最全总结&#xff08;附详细思维导图&#xff09; 本篇开始&#xff0c;先奉上思维导图&#xff1a;&#xff08;下载下来为超高清图&#xff0c;不愁小伙伴看不清&#xff01;&#xff09; 按流的方向分类&#xff1a; 输入流&#xff1a;数据源到程序(InputStr…...

易基因:ChIP-seq等揭示BRWD3调控KDM5活性以维持H3K4甲基化水平的表观机制|PNAS

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 组蛋白修饰对调控染色质结构和基因表达至关重要&#xff0c;组蛋白修饰失调可能导致疾病状态和癌症。染色质结合蛋白BRWD3&#xff08;Bromodomain and WD repeat-containing protein 3&…...

C++深度优先(DFS)算法的应用:收集所有金币可获得的最大积分

涉及知识点 深度优化(DFS) 记忆化 题目 节点 0 处现有一棵由 n 个节点组成的无向树&#xff0c;节点编号从 0 到 n - 1 。给你一个长度为 n - 1 的二维 整数 数组 edges &#xff0c;其中 edges[i] [ai, bi] 表示在树上的节点 ai 和 bi 之间存在一条边。另给你一个下标从 0…...

uniapp中APP端使用echarts用formatter设置y轴保留2位小数点不生效

uniapp使用echarts&#xff0c;在内置浏览器中&#xff0c;设置保留2位小数能正常显示&#xff08;代码如下&#xff09;&#xff0c;但是在APP端这个设置不起作用。 yAxis: {type: value,axisLabel: {formatter: function (val) {return val.toFixed(2); //y轴始终保留小数点…...

无糖茶饮三十年,从无人问津到人手一瓶

【潮汐商业评论/原创】 Joan又在外卖上点了一堆瓶装茶饮&#xff0c;东方树叶、燃茶、三得利乌龙茶……买了四五种纯茶&#xff0c;用她的话说&#xff0c;和美式咖啡相比&#xff0c;这些无糖茶更适合他这个中国体质。 事实上&#xff0c;越来越多的消费者开始像Joan一样&am…...

面向Three.js开发者的3D自动纹理化开发包

DreamTexture.js 是面向 three.js 开发者的 3D 模型纹理自动生成与设置开发包&#xff0c;可以为 webGL 应用增加 3D 模型的快速自动纹理化能力。 图一为原始模型, 图二图三为贴图后的模型。提示词&#xff1a; city, Realistic , cinematic , Front view ,Game scene graph 1、…...

数字孪生技术与VR:创造数字未来

在当今数字化浪潮中&#xff0c;数字孪生和虚拟现实&#xff08;VR&#xff09;技术是两大亮点&#xff0c;它们以独特的方式相互结合&#xff0c;为各个领域带来了创新和无限可能。本篇文章将探讨数字孪生与VR之间的关系&#xff0c;以及它们如何共同开辟未来的新前景。 数字…...

系统架构设计师-第15章-面向服务架构设计理论与实践-软考学习笔记

面向服务的体系结构&#xff08;Service-Oriented Architecture, SOA) 面向服务的体系结构&#xff08;Service-Oriented Architecture, SOA&#xff09;是一种软件架构模式&#xff0c;它将应用程序的不同功能组织为一组可重用的、松耦合的、自治的服务&#xff0c;这些服务通…...

为什么我觉得Rust比C++复杂得多?

为什么我觉得Rust比C复杂得多&#xff1f; Rust自学确实有一定门槛&#xff0c;很多具体问题解决起来搜索引擎也不太帮的上忙&#xff0c;会出现卡住的情况&#xff0c;卡的时间长了就放弃了。最近很多小伙伴找我&#xff0c;说想要一些c语言资料&#xff0c;然后我根据自己从…...

python sqlalchemy(ORM)- 03 增删改查

文章目录 ORM更新数据ORM查询ORM删除操作处理关系对象多表的关联查询 本节所有案例基于&#xff08;第一节 python sqlalchemy&#xff08;ORM&#xff09;- 01 ORM简单使用&#xff09;中的User、Address两个模型类 ORM更新数据 查询到模型类对象&#xff0c;直接修改其属性…...

Flutter笔记:完全基于Flutter绘图技术绘制一个精美的Dash图标(上)

Flutter笔记 完全基于Flutter绘图技术绘制一个精美的Dart语言吉祥物Dash&#xff08;上&#xff09; 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://…...

学习gorm:彻底弄懂Find、Take、First和Last函数的区别

在gorm中&#xff0c;要想从数据库中查找数据有多种方法&#xff0c;可以通过Find、Take和First来查找。但它们之间又有一些不同。本文就详细介绍下他们之间的不同。 一、准备工作 首先我们有一个m_tests表&#xff0c;其中id字段是自增的主键&#xff0c;同时该表里有3条数据…...

796. 子矩阵的和(二维前缀和)

题目&#xff1a; 796. 子矩阵的和 - AcWing题库 思路&#xff1a; 1.暴力搜索&#xff08;搜索时间复杂度为O(n2)&#xff0c;很多时候会超时&#xff09; 2. 前缀和&#xff08;左上角&#xff08;二维&#xff09;前缀和&#xff09;&#xff1a;本题特殊在不是直接求前…...

智能视频转PPT:3分钟实现视频内容自动提取的完整方案

智能视频转PPT&#xff1a;3分钟实现视频内容自动提取的完整方案 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 你是否曾为整理会议录像中的PPT内容而烦恼&#xff1f;手动暂停、截…...

学习规划需要定期调整吗?

在当今竞争激烈的教育环境中&#xff0c;学习规划对于学生的成长和发展起着至关重要的作用。作为一名在学习规划领域深耕十年的专家&#xff0c;我见证了无数学生在学习规划的指引下取得优异成绩&#xff0c;也看到了一些学生因为规划不合理而走了不少弯路。那么&#xff0c;学…...

Visual C++ 运行库一体化解决方案:跨版本兼容性管理实践

Visual C 运行库一体化解决方案&#xff1a;跨版本兼容性管理实践 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist Windows 应用程序依赖的 Visual C 运行库版本碎…...

Rust 服务器存档管理 地图配置指南

对于想要自建游戏服务器的玩家&#xff0c;云鸢互联是一个不错的专业联机平台选择。它提供稳定、低延迟且724小时在线的服务器环境&#xff0c;助你轻松打造专属游戏世界。平台主打极致的新手友好——全图形化控制面板&#xff0c;无需编写代码&#xff0c;也无需掌握Linux命令…...

EPM900编程器HEX文件烧录指南与技巧

1. EPM900编程器与HEX文件烧录概述 EPM900是Keil公司推出的一款LPC系列微控制器仿真编程器&#xff0c;主要用于NXP LPC系列ARM芯片的调试与程序烧录。在实际工程开发中&#xff0c;我们经常需要将编译生成的HEX文件直接烧录到目标芯片中&#xff0c;而EPM900恰好支持这一功能。…...

稳定币深度解析:从技术内核到生态未来

稳定币深度解析&#xff1a;从技术内核到生态未来 引言 在加密货币世界剧烈波动的浪潮中&#xff0c;稳定币如同一座坚不可摧的桥梁&#xff0c;连接着传统金融与去中心化未来。它不仅是DeFi乐高积木中最关键的基座&#xff0c;更在跨境支付、元宇宙经济等前沿领域扮演着核心…...

Perplexity搜索功能隐藏入口全解锁:9个未公开Pro技巧,第7个连官方文档都没写!

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Perplexity搜索功能隐藏入口全解锁&#xff1a;现象与价值重估 Perplexity.ai 的公开界面长期以简洁问答框为核心&#xff0c;但其底层实际嵌套了多组未在UI中显式暴露的高级搜索能力——包括语义过滤、…...

从理论到PCB:20dB耦合度的宽带定向耦合器设计全流程与性能测试

从理论到PCB&#xff1a;20dB耦合度的宽带定向耦合器设计全流程与性能测试 在射频电路设计中&#xff0c;定向耦合器作为关键的无源器件&#xff0c;其性能直接影响整个系统的信号监测、功率分配和反射测量精度。特别是工作于1-4GHz频段、耦合度为20dB的宽带定向耦合器&#xf…...

【Perplexity文献管理终极指南】:20年科研老炮亲授AI时代参考文献零误差管理法

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Perplexity文献管理的底层逻辑与范式革命 Perplexity 并非传统意义上的本地文献数据库工具&#xff0c;其核心突破在于将文献管理从“静态存储—手动索引”范式&#xff0c;跃迁至“动态语义理解—上下…...

C语言泛型编程与类型安全 - C11的高级特性

引言 C语言通常被认为不支持泛型编程,但实际上通过巧妙的设计模式和C11标准的新特性,我们可以在C语言中实现类型安全的泛型代码。 本文将深入讲解如何使用void指针、宏技巧和C11的_Generic关键字实现泛型编程,让你的代码更加灵活和可复用。 一、void指针泛型基础 1.1 vo…...