108. 将有序数组转换为二叉搜索树
题目描述
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
题解:
一个直观的贪心策略:取区间 [l, r]
的中点 mid
作为根节点的值,然后递归建左右子树。
下面我们来证明上述的构造方法得到的 BST 满足任意节点的左右子树的所有高度的差不大于1。
假设在每一次递归过程中,左半部分的长度最多比右半部分长度少 1
,那么需要判断会不会出现下面这种情况:
- 左半部分子树高度为
m - 1
,右半部分子树高度为m + 1
如果左半部分子树高度为 m - 1
,那么左子树节点个数最多为
2
m
−
2
2^m - 2
2m−2 个;如果右半部分子树高度为 m + 1
,那么右子树节点个数最少为
2
m
2^m
2m 。两边差值最少为 2
,所以不可能出现上述情况,即该方法构造的 BST 是平衡的。
时间复杂度: O ( n ) O(n) O(n)
额外空间复杂度: O ( l o g n ) O(logn) O(logn)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
void build( TreeNode*& root, int l, int r, vector<int>& nums ) {
if ( l > r ) return;
int mid = (l + r) >> 1;
root = new TreeNode( nums[mid] );
build( root->left, l, mid - 1, nums );
build( root->right, mid + 1, r, nums );
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode *root = nullptr;
build( root, 0, nums.size() - 1, nums );
return root;
}
};
/*
时间:16ms,击败:97.60%
内存:22.4MB,击败:97.80%
*/