LeetCode | Convert Sorted List to Binary Search Tree

来源:互联网 发布:淘宝能贷款能贷多少 编辑:程序博客网 时间:2024/06/03 21:35

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

将链表转换为平衡二叉搜索树。
平衡的要点是取到中点的数据,搜索树的要点是左小右大(排好序的链表已经帮我们实现了这一点)

相比较数组,链表需要寻找开始和末尾节点。
并且在划分区间的时候,需要找到划分节点的prev节点。
这样一般是使用prev=start,temp=prev->next;并成功找到目的temp节点,prev节点即为所需。

但是需要注意start=end的时候需要特判,这时候prev和next都应当=NULL

class Solution {public:    TreeNode* sortedListToBST(ListNode* head) {        ListNode* temp=head;        while(temp && temp->next) temp=temp->next;        return generate(head,temp);    }    //时间复杂度T(n)=2T(n/2)+n 即O(nlogN)    TreeNode* generate(ListNode* start,ListNode* end){        int n=1;        if(!start || !end) return NULL;        //边界条件        ListNode* temp=start;        for(;temp && temp!=end;temp=temp->next,n++);        if(temp!=end) return NULL;        //获取中值        //需要获取到中值的prev和next        ListNode *prev,*next;        //仅有一个值        if(start==end){            prev=NULL;next=NULL;            temp=end;        }        else{            prev=start;temp=prev->next;            for(int i=1;temp && i<n/2;i++,temp=temp->next,prev=prev->next);            next=temp?temp->next:NULL;        }        printf("val %d\n",temp->val);        //获取到temp为中点,prev为其前缀,next为后缀        TreeNode* node=new TreeNode(temp->val);        node->left=generate(start,prev);        node->right=generate(next,end);        return node;    }};

寻找中位数和之后写的不是很优雅。
然后在讨论区看到了比较好的思路:
引出这个思路,我们可以考虑一下:如何在O(n)的时间内找到一个链表的中位数


答案:使用双指针,一个fast每次走两步,另一个slow每次走一步。
和之前链表题里面一道追赶的题目颇为类似;

// fast/slow pointer to find the midpointauto slow = head;auto fast = head;auto pre = head;while(fast && fast->next) {    pre = slow;    slow = slow->next;    fast = fast->next->next;}pre->next = 0; // break two halves // slow is the midpoint, use as rootTreeNode* root = new TreeNode(slow->val);root->left = sortedListToBST(head);root->right = sortedListToBST(slow->next);

另外,有一种O(n)的做法

可以通过模拟中序遍历的方法,先递归出左子树,接着将左子树的节点赋值给当前node,再递归求出节点的右子树。
这种方法不太常规,因为一般都是已知了一个节点之后去递归生成两个孩子节点。

    //时间O(n) 空间O(logN)     TreeNode* sortedToBST(ListNode* &head,int start,int end){        if(start>end) return NULL;        int mid=start+(end-start)/2;//获取中间下标        TreeNode* left=sortedToBST(head,start,mid-1);        TreeNode* parent=new TreeNode(head->val);        parent->left=left;        //等于使用中序遍历,        head=head->next;        parent->right=sortedToBST(head,mid+1,end);        return parent;    }
0 0