高度平衡的二叉搜索树(又叫二叉排序树)
- 左子树小于根节点,右子树大于根节点。
- 左右两边高度差小于等于1
- 每个节点都是一个二叉搜索树
方法一:分治
- 由于二叉搜索树的性质,再加上题目中所给的是一个排好顺序的数组,所以只需找到中位数,插入到根节点即可。
- 再分别从中位数左右两边取中位数,分别插到上一个结点的左右子树上。
- 我们取得区间为左闭右开区间!!
代码:
struct ListNode* getMidPoint(struct ListNode* left,struct ListNode* right){
struct ListNode* slow = left;
struct ListNode* fast = left;
while(fast != right && fast->next != right){
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
struct TreeNode* Tree(struct ListNode* left,struct ListNode* right){
if(left == right) return NULL;
struct ListNode* mid = getMidPoint(left,right);
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->val = mid->val;
root->left = root->right = NULL;
root->left = Tree(left,mid);
root->right = Tree(mid->next,right);
return root;
}
struct TreeNode* sortedListToBST(struct ListNode* head){
return Tree(head,NULL);
}
做进一步改进:
我们已经知道,上一个方法所浪费的时间是在查找中位数的步骤上,所以我们根据二叉搜索树的一个性质做出改进:二叉搜索树的中序遍历为有序数组。
所以我们做出如下改进:
- 首先算出数组长度
- 在建立二叉树时,遵循中序遍历,即:左,根,右
代码:
int getLength(struct ListNode* head){
int ans = 0;
while(head != NULL){
ans++;
head = head->next;
}
return ans;
}
struct TreeNode* buildTree(struct ListNode** head,int left,int right){
if(left > right) return NULL;
int mid = (left + right +1)/2;
struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
root->left = buildTree(head,left,mid-1);
root->val = (*head)->val;
(*head) = (*head)->next;
root->right = buildTree(head,mid+1,right);
return root;
}
struct TreeNode* sortedListToBST(struct ListNode* head){
int length = getLength(head);
return buildTree(&head,0,length-1);
}