题目描述
给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树。
示例:
给定有序数组: [-10,-3,0,5,9],
一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
0
/ \
-3 9
/ /
-10 5
解题思路与代码
做这道题,需要你对二叉树这种数据结构有基本的了解,知道什么叫做二叉搜索树。并且知道基本的递归函数怎么写,递归函数的三要素是什么。
这道题给了我们一个有序的数组,让我们把它变成一颗二叉搜索树,且这个二叉搜索树的高度要最小。首先我们知道二叉搜索树的性质,那就是左边节点小于中间节点,中间节点小于右边节点。它要求高度最小,我们就把数组最中间的那个元素拿出来做中间节点,那出来的二叉树的高度必然是最小的。(自己随便画一下就知道)
中序遍历法(中间或中间靠左边节点做中间节点)
这个方法要求我们选取数组最中间,或最中间偏左的元素取出来做中间节点。
首先,我们要自己去写一个新的递归函数。因为原函数只能传递一个参数,我们施展不开手脚。新的递归函数的返回类型还是TreeNode*类型,我们需要传入三个参数,分别一个是一直存在的数组,一个是左起始点,一个是右结束点。
然后就是基本的逻辑判断了。
需要注意的是,数组的下标。不要越界了。这个是这道题唯一需要注意的点。
请注意这一行代码:int mid = (end + begin) / 2 ;
注意这里一定是end + begin
,而不是end - begin。这是阿宋以前经常犯下的错误,希望你们以后不要再犯。
具体的代码如下:
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
return inorderTraversal(nums,0,nums.size()-1);
}
TreeNode* inorderTraversal(vector<int>& nums,int begin,int end){
if(begin > end) return nullptr;
int mid = (end + begin) / 2 ;
TreeNode* head = new TreeNode(nums[mid]);
head->left = inorderTraversal(nums,begin,mid-1);
head->right = inorderTraversal(nums,mid+1,end);
return head;
}
};
复杂度分析
时间复杂度:
- O(n),其中n等于数组nums中的元素数量。因为我们的代码采用递归的方式去编写,在每次递归的时候都去查找一个区间中的mid值,并创建占用常数时间的TreeNode节点。然后递归调用左边的子范围和右边的子范围。
空间复杂度:
- O(logn),由于我们每次递归调用区间长度都会缩小到原来的一半,所以我们需要递归log2^n 次才能将区间变空,所以就消耗了O(logn)的堆栈空间,所以空间复杂度就是O(logn)。
总结
这道题不是什么难题,只要你基础知识扎实,分分钟就做出来。如果基础不扎实也没关系,努力夯实基础就行。