LeetCode-hot100——将有序数组转换为二叉搜索树
将有序数组转换为二叉搜索树
题目链接:将有序数组转换为二叉搜索树
题目分析
本题要求将一个升序排列的整数数组转换为一棵平衡二叉搜索树。平衡二叉搜索树需满足两个条件:
- 是二叉搜索树:对于树中任意节点,其左子树所有节点值小于它,右子树所有节点值大于它。
- 是平衡树:左右子树的高度差不超过 1。
解题思路(分治思想)
利用数组升序排列的特性,采用分治策略构建平衡二叉搜索树:
- 选中间元素为根:将数组中间位置的元素作为当前子树的根节点,这样能保证左右子树节点数量尽可能相等,初步实现 “平衡”。
- 递归构建左右子树:
- 根节点左子树:由数组左半部分(
[左边界, 中间位置 - 1]
)递归构建。 - 根节点右子树:由数组右半部分(
[中间位置 + 1, 右边界]
)递归构建。
- 根节点左子树:由数组左半部分(
代码详解
class Solution {
public:// 递归函数:将 nums[l...r] 转换为平衡二叉搜索树TreeNode* seek(vector<int>& nums, int l, int r) {// 递归终止条件:区间无效(l > r),返回空节点if (l > r) return nullptr;// 取中间位置元素作为根节点int mid = (l + r) / 2;TreeNode* root = new TreeNode(nums[mid]);// 递归构建左子树(左半区间 [l, mid - 1])root->left = seek(nums, l, mid - 1);// 递归构建右子树(右半区间 [mid + 1, r])root->right = seek(nums, mid + 1, r);return root;}// 主函数:调用递归,初始区间为 [0, nums.size() - 1]TreeNode* sortedArrayToBST(vector<int>& nums) {return seek(nums, 0, static_cast<int>(nums.size() - 1));}
};
图解样例
以 nums = [-10, -3, 0, 5, 9]
为例10
初始数组:
索引: 0 1 2 3 4
值: -10 -3 0 5 9
构建根节点(整体区间 [0,4])
- 计算中间位置:
mid = (0+4)/2 = 2
,对应值0
- 根节点为
0
- 左子树区间:
[0,1]
(元素:-10, -3) - 右子树区间:
[3,4]
(元素:5, 9)
0/ \
[0,1] [3,4]
构建左子树(区间 [0,1])
- 计算中间位置:
mid = (0+1)/2 = 0
,对应值-10
- 该节点作为根节点的左孩子
- 左子树区间:
[0,-1]
(无效,为空) - 右子树区间:
[1,1]
(元素:-3)
0/ \-10 [3,4]/ \空 [1,1]
构建左子树的右子树(区间 [1,1])
- 计算中间位置:
mid = 1
,对应值-3
- 该节点作为
-10
的右孩子 - 左右子树区间均无效(为空)
0/ \-10 [3,4]/ \空 -3/ \空 空
构建右子树(区间 [3,4])
- 计算中间位置:
mid = (3+4)/2 = 3
,对应值5
- 该节点作为根节点的右孩子
- 左子树区间:
[3,2]
(无效,为空) - 右子树区间:
[4,4]
(元素:9)
0/ \-10 5/ \ / \空 -3 空 [4,4]/ \空 空
构建右子树的右子树(区间 [4,4])
- 计算中间位置:
mid = 4
,对应值9
- 该节点作为
5
的右孩子 - 左右子树区间均无效(为空)
0/ \-10 5/ \ \空 -3 9/ \ / \空 空 空 空
最终平衡二叉搜索树结构
0/ \-10 5\ \-3 9
反思
为什么这样构建是平衡的?
- 根节点
0
的左子树高度为 2,右子树高度为 2,差值为 0 - 节点
-10
的左子树高度为 0,右子树高度为 1,差值为 1 - 节点
5
的左子树高度为 0,右子树高度为 1,差值为 1 - 所有节点的左右子树高度差都不超过 1,满足平衡二叉树的定义
通过这种 "选择中间元素作为根节点" 的分治策略,我们确保了构建出的二叉搜索树是平衡的,因为每次都会将当前区间均匀地分成两部分。