Problem Description:
Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.
分析:很容易想到的一种解法是将链表中所有的元素保存到数组中,然后每次取中间值进行构造,时间复杂度为O(n),空间复杂度为O(n)。具体实现如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* createTree(vector<ListNode *> &listvec,int begin,int last)
{
if(begin>last)
return NULL;
if(begin==last)
{
int val=listvec[begin]->val;
TreeNode *head=new TreeNode(val);
return head;
}
else
{
int mid=(begin+last)/2;
int val=listvec[mid]->val;
TreeNode *head=new TreeNode(val);
head->left=createTree(listvec,begin,mid-1);
head->right=createTree(listvec,mid+1,last);
return head;
}
}
TreeNode *sortedListToBST(ListNode *head) {
TreeNode *Treehead=NULL;
if(head==NULL)
return Treehead;
vector<ListNode *> listvec;
ListNode *p=head;
while(p)
{
listvec.push_back(p);
p=p->next;
}
Treehead=createTree(listvec,0,listvec.size()-1);
return Treehead;
}
};
当然,可以直接遍历链表每次找到中间值,递归构造二叉树,时间复杂度为O(nlogn),空间复杂度为O(log(n)),但是自己无意间在网上看到一种时间复杂度为O(n),空间复杂度为O(1)的解法,思路需要变换一下,正常的递归都是自上而下,而这里利用的是自底向上的方法,在递归中传递的是同一个链表,只是这个链表的节点不停往前走,而真正决定性变化的是区间,每次递归调用时,分成左右两部分,左边构造完时,正好指针指向mid,然后创建一个root,继续构造右部分子树。具体代码如下:
TreeNode *sortedListToBST(ListNode *head) {
int len = 0;
ListNode * node = head;
while (node != NULL)
{
node = node->next;
len++;
}
return buildTree(head, 0,len-1);
}
TreeNode *buildTree(ListNode *&node, int start, int end)
{
if (start > end) return NULL;
int mid = start + (end - start) / 2;
TreeNode *left = buildTree(node, start, mid-1);
TreeNode *root = new TreeNode(node->val);
root->left = left;
node = node->next;
root->right = buildTree(node, mid+1, end);
return root;
}