当前位置: 首页 > 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;本题特殊在不是直接求前…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...