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

【LeetCode热题100道笔记】将有序数组转换为二叉搜索树

题目描述

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

示例 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 按 严格递增 顺序排列

思考:分治思想构建平衡BST

核心是分治递归:每次取数组中间元素作为当前根节点,将数组分为“左子数组”(根左侧元素)和“右子数组”(根右侧元素),分别递归构建左、右子树——左子数组构建左子树(值均小于根),右子数组构建右子树(值均大于根),最终形成平衡BST。

采用左闭右开区间 [start, end) 划分数组,可简化边界处理(终止条件为 start >= end,即空区间)。

算法过程

  1. 初始化递归:调用辅助函数 buildBST,传入数组 nums 及初始区间 [0, nums.length)(覆盖整个数组)。
  2. 递归终止条件:若区间 start >= end(空区间,无元素可构建节点),返回 null
  3. 构建当前根节点
    • 计算区间中点 mid = start + Math.floor((end - start) / 2)(用此写法避免 start + end 溢出);
    • nums[mid] 为值创建当前根节点,确保根节点是区间中间元素,左右子树元素数量差≤1(保证平衡)。
  4. 递归构建子树
    • 左子树:用左子区间 [start, mid) 递归构建(元素均小于当前根,满足BST左子树特性);
    • 右子树:用右子区间 [mid+1, end) 递归构建(元素均大于当前根,满足BST右子树特性)。
  5. 返回结果:递归回溯时,返回当前根节点,最终形成完整的平衡BST。

时空复杂度

  • 时间复杂度:O(n),n为数组长度。
    原因:每个数组元素仅被用于创建一个节点(递归过程中每个元素对应一个根/子节点),每个节点的构建操作(创建节点、递归调用)均为O(1),总操作次数与数组长度线性相关。
  • 空间复杂度:O(log n),n为数组长度。
    原因:递归调用栈深度取决于平衡BST的高度——平衡BST的高度为 log n(如n=5时高度2,n=7时高度3),最坏情况下(无额外空间消耗),空间复杂度由递归栈决定,为O(log n)。

代码(左闭右开区间实现)

/*** Definition for a binary tree node.* function TreeNode(val, left, right) {*     this.val = (val===undefined ? 0 : val)*     this.left = (left===undefined ? null : left)*     this.right = (right===undefined ? null : right)* }*/
/*** @param {number[]} nums* @return {TreeNode}*/
var sortedArrayToBST = function(nums) {// 初始区间:左闭右开 [0, nums.length),覆盖整个数组return buildBST(nums, 0, nums.length);
};// 辅助函数:基于区间 [start, end) 构建平衡BST
function buildBST(nums, start, end) {// 终止条件:空区间(无元素可构建节点),返回nullif (start >= end) return null;// 计算中点:避免 start + end 溢出(如start和end均接近Number.MAX_SAFE_INTEGER)const mid = start + Math.floor((end - start) / 2);// 以中点元素为根,保证左右子树元素数量差≤1,天然平衡const root = new TreeNode(nums[mid]);// 递归构建左子树:左子区间 [start, mid)(元素均小于root.val)root.left = buildBST(nums, start, mid);// 递归构建右子树:右子区间 [mid+1, end)(元素均大于root.val)root.right = buildBST(nums, mid + 1, end);return root;
}

关键逻辑解析

  1. 为何选中间元素为根?
    升序数组的中间元素可将数组分为“长度相等或差1”的左右子数组,递归构建的左右子树高度差≤1,天然满足“平衡”要求;同时,左子数组元素均小于中间元素、右子数组均大于中间元素,满足BST的数值特性。

  2. 为何用左闭右开区间?
    左闭右开区间的终止条件 start >= end 更简洁(空区间直接返回null),且子区间划分无需调整边界(左子树 [start, mid)、右子树 [mid+1, end),无重叠且覆盖原区间),避免左闭右闭区间中 start > end 的复杂判断。

  3. 中点计算的溢出问题
    若直接写 mid = Math.floor((start + end) / 2),当 startend 均接近最大值时,start + end 可能超出JavaScript整数安全范围,导致计算错误;而 start + Math.floor((end - start) / 2) 可避免此问题,结果与前者一致且更安全。

http://www.xdnf.cn/news/20482.html

相关文章:

  • 3分钟快速入门WebSocket
  • Scikit-learn Python机器学习 - 特征降维 压缩数据 - 特征提取 - 主成分分析 (PCA)
  • dify+Qwen2.5-vl+deepseek打造属于自己的作业帮
  • 第27节:3D数据可视化与大规模地形渲染
  • 如何下载小红书视频
  • MySQL的组复制(MGR)高可用集群搭建
  • vue3图标终极方案【npm包推荐】vue3-icon-sui(含源码详解)
  • STM32F4芯片RS485使用记录
  • 小迪自用web笔记29
  • 少儿配音教育:广州声与色在线科技有限公司打造趣味课程,助力青少年语言能力提升
  • 电脑外接显示屏字体和图标过大
  • 实体商业创新观察:AI 驱动的本地生活服务新模式解析
  • 计算机网络:物理层---物理层的基本概念
  • OpenSSL 1.0.1e 下载解压和运行方法(小白适用 附安装包)​
  • Nginx性能调优:参数详解与压测对比
  • 小孔成像原理
  • 吴恩达机器学习(九)
  • 正态分布 - 正态分布的标准化
  • 音视频技术全景:从采集到低延迟播放的完整链路解析
  • 【鸿蒙 NEXT】V1迁移V2状态管理
  • VMWare和centOS的安装
  • 集成学习 —— 梯度提升树GBDT、XGBoost
  • Javaweb 14.4 Vue3 视图渲染技术
  • 【MySQL | 高级篇 分片规则与管理监控】
  • 从Java全栈到前端框架的全面实战:一次真实面试的深度解析
  • c++ sqlite3库
  • CentOS下Bind服务的安装与故障排查
  • pyAutoGUI 模块主要功能介绍-(1)鼠标功能
  • 从 Excel 趋势线到机器学习:拆解 AI 背后的核心框架​
  • 数位DP -