首先来看一个简单的例子,如何将有序数组转换为平衡二叉树?
模拟堆排序的方式,如果每次把数组的中位数当作根节点,把中位数左边的序列的中位数当作左子节点,右边的序列的中位数当作右子节点,递归上面的过程即可得到一个平衡二叉树。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode * arr2BST(vector<int>& nums, int start, int end) {
if (start > end) {
return NULL;
}
int mid = start + (end - start) / 2;
TreeNode * root = new TreeNode(nums[mid]);
root->left = arr2BST(nums, start, mid-1);
root->right = arr2BST(nums, mid+1, end);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
if(nums.size() == 0) {
return NULL;
}
return arr2BST(nums, 0, nums.size() - 1);
}
};
类似的,我们想想也可以将链表看作是数组,由于上面的过程中,上面的过程中,主要有两个地方需要转换为链表的操作,即start和end是数组的下标,我们需要转换为链表的节点,每次计算出mid,然后next大法计算出当前节点后第mid个节点即可。思考一下时间复杂度,由于每次找mid节点都会做比较,由于是折中查找所以时间复杂度是lgn,所以时间复杂度是nlgn。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode * list2BST(ListNode * head, int start, int end) {
if (start > end) {
return NULL;
}
if (start == end) {
return new TreeNode(head->val);
}
int mid = (end - start) / 2;
ListNode * p = head;
for (int i = 0; i < mid && p != NULL; ++i) {
p = p->next;
}
if (p == NULL) {
return NULL;
}
TreeNode * root = new TreeNode(p->val);
root->left = list2BST(head, start, mid-1);
root->right = list2BST(p->next, mid+1, end);
return root;
}
TreeNode* sortedListToBST(ListNode* head) {
if (head == NULL) {
return NULL;
}
int end = 0;
for (ListNode * p = head; p != NULL; p=p->next, ++end);
return list2BST(head, 0, end-1);
}
};
当然,这里的时间消耗在查找mid节点,假如存在函数f,f遍历链表的某个序列的时候总是返回这个序列的中间节点,那么就不用for循环找mid节点了。这种自底而上的形式非常类似于二叉树的中序遍历。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode * list2BST(ListNode * &head, int start, int end) {
if (start > end) {
return NULL;
}
int mid = start + (end - start) / 2;
TreeNode * left = list2BST(head, start, mid-1);
TreeNode * root = new TreeNode(head->val);
root->left = left;
head = head->next;
root->right = list2BST(head, mid+1, end);
return root;
}
TreeNode* sortedListToBST(ListNode* head) {
if (head == NULL) {
return NULL;
}
int end = 0;
for (ListNode * p = head; p != NULL; p=p->next, ++end);
return list2BST(head, 0, end-1);
}
};
在上面的代码中,从底向上,依次告诉上层递归:“我是left,是左子序列的中间节点,我是right,我是右子序列的中间节点”。