方案1:找中间结点作为root + recursively 建立左右子树
1)快慢指针法找中间结点mid,作为root,
2) recursive problem: head 到 prev 这一段链表建立左子树, mid->next 到结尾这一段链表建立右子树
复杂度分析:T(n) = 2T(n/2) + n/2 应该是 (n/2) * lgn
TreeNode *sortedListToBST(ListNode *head) {
// write your code here
if(head==NULL) return NULL;
if(head->next==NULL) return new TreeNode(head->val);
auto p=head,q=head,preP=head;
while(q && q->next)
{
preP=p;
p=p->next;
q=q->next->next;
}
preP->next=NULL;
auto root = new TreeNode(p->val);
root->left=sortedListToBST(head);
root->right=sortedListToBST(p->next);
return root;
}
方案2:自底向上
定义一个函数 ListNode * sortedListToBST(ListNode *head, int start, int end),含义为:将start和end对应的结点转化成二叉树,同时指针推进到end之后
1)建立左子树,同时链表指针推进过处理过的结点
2)当前结点所为root
3) 建立右子树,同时链表指针推进过处理过的结点
TreeNode *sortedListToBST(ListNode *head) {
// write your code here
int n = 0;
for (auto p = head; p; p = p->next) ++n;
return sortedListToBST(head, 0, n - 1);
}
TreeNode* sortedListToBST(ListNode* &head, int start, int end) {
if (start > end) return NULL;
int mid = start + (end - start) / 2;
auto left = sortedListToBST(head, start, mid - 1);
auto root = new TreeNode(head->val);
root->left = left;
head = head->next;
root->right = sortedListToBST(head, mid + 1, end);
return root;
}
在链表上用到了数组场景的start, end,mid,很是新颖。其作用是在top-down的时候划分好子树,自底向上构建tree的时候按照这个轨迹回溯就好了。