跳到正文
第 108 题简单

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

Convert Sorted Array to Binary Search Tree

把升序数组转换成一棵高度平衡的二叉搜索树。

在力扣中练习

题目描述

给你一个整数数组 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 的中序遍历是升序,所以升序数组本身就是某棵 BST 的中序序列。要让树尽量平衡,根应当取当前区间的中点。

取 mid = (l + r) / 2 创建根,递归用 [l, mid-1] 建左子树、[mid+1, r] 建右子树。左右区间长度最多差 1,因此树高是 O(log n)。

分步图解

有序数组的中点是根,左边全部更小、右边全部更大;先建根,再递归两侧。

构造中的 BST · 浅色节点尚未创建左子树 · 右子树
·······
nums · 当前区间 [0,6]
0
1
2
3
4
5
6
-8
-3
0
4
7
11
15
1 / 3
中点 4 先成为根;左区间继续取 -3,右区间稍后处理。

自拟数组有 7 个元素,根取下标 3 的 4;左区间 [−8,−3,0] 取 −3,右区间 [7,11,15] 取 11。这样每个节点的左右子树高度差不超过 1。

分步图解

区间 [4,6] 的中点 5,取 11 作为当前子树的根。

mid
5
构造中的 BST · 浅色节点尚未创建左子树 · 右子树
-8-304·11·
nums · 当前区间 [4,6]
0
1
2
3
4
5
6
-8
-3
0
4
7
11mid
15
1 / 3
右区间 [7,11,15] 取 11 为根,再挂上 7 和 15。

答案不唯一:偶数长度时取左中点或右中点都能得到合法平衡树,LeetCode 会校验任意合法答案。关键是每个节点都满足左小右大,并且高度平衡。

时间 O(n)空间 O(log n) 递归栈

易错点

  • mid 写成 (l+r)/2 后忘记用局部变量:递归会覆盖上一层的中点。
  • 区间写成左闭右闭却用 l < r:漏掉单元素区间。
  • 取端点当根:树退化成链,不满足平衡要求。

代码与演示

演示输入nums = [-8,-3,0,4,7,11,15]

有序数组的中点是根,左边全部更小、右边全部更大;先建根,再递归两侧。

构造中的 BST · 浅色节点尚未创建左子树 · 右子树
·······
nums · 当前区间 [0,6]
0
1
2
3
4
5
6
-8
-3
0
4
7
11
15
1 / 3
查看 C++ 代码

延伸阅读

  • “有序数组 ↔ 平衡 BST”是同一份信息的两种表示,中点分治保证平衡。
  • 如果数组含重复值,需要先明确重复元素放在左侧还是右侧,再决定边界。