本来以为题目比较简单,就是每次以中间元素作为父节点递归简历左右子树。
优化:先把链表元素存入vector中,便于快速存取中间元素。
/**
* 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 *_build(vector<int> &v, int start, int end){
if(start>end)
return NULL;
if(start == end)
return new TreeNode(v[start]);
int mid = (start+end+1)/2;
TreeNode *node = new TreeNode(v[mid]);
node->left = _build(v,start,mid-1);
node->right = _build(v,mid+1,end);
return node;
}
TreeNode *sortedListToBST(ListNode *head) {
if(head==NULL)
return NULL;
vector<int> v;
while(head){
v.push_back(head->val);
head = head->next;
}
int start = 0;
int end = v.size()-1;
TreeNode *root = _build(v,start,end);
return root;
}
};
后来发现,还有一题是给你List Array,那跟这题有什么区别?所以肯定还是用List来做。如果遍历list获得中间元素的话,总的时间复杂度则需要O(NlogN)。
Leetcode官网给出了O(N)的解法,非常精妙,从底向上建树,只需要顺序遍历List一次即可。而且代码非常简洁,只是不太容易想得到。注意_build函数的ListNode参数为引用。
class Solution {
public:
TreeNode *_build(ListNode *&head, int start, int end){
if(start > end)
return NULL;
int mid = start + (end-start)/2;
TreeNode *left = _build(head,start,mid-1);
TreeNode *father = new TreeNode(head->val);
father->left = left;
head = head->next;
father->right = _build(head,mid+1,end);
return father;
}
TreeNode *sortedListToBST(ListNode *head) {
ListNode *tmp = head;
int len=0;
while(tmp){
++len;
tmp = tmp->next;
}
TreeNode *root = _build(head,0,len-1);
return root;
}
};