LeetCode | Convert Sorted List to Binary Search Tree

100 篇文章 0 订阅
28 篇文章 0 订阅

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 midpoint
auto 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 root
TreeNode* 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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值