【LeetCode】148. 排序链表

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

根据时间复杂度选择归并排序,解题思路如下:

1.使用归并排序前,找到中间节点pmiddle,因为是链表排序所以我们要找到的是中间节点的前继节点,使用快慢指针可以完成,需要注意的是分隔成两个链表时,前链表的最后一个节点指向空。

2.对前后两部分再分别进行归并排序。

3.合并两个有序链表,同样最后一个节点指向空。

ListNode* Solution::sortList(ListNode* head)
{
    if((head == NULL) || (head->next == NULL))
    {
        return head;
    }
    /*1.使用归并排序前,找到中间节点pmiddle*/
    /*前移一个节点开始寻找是为了找到中间节点的前继*/
    ListNode *pnext = new ListNode(0);
    ListNode *pmiddle = pnext;
    ListNode *pmiddlefast = pnext;
    pnext->next = head;
    while((pmiddlefast != NULL) && (pmiddlefast->next != NULL))
    {
        pmiddle = pmiddle->next;
        pmiddlefast = pmiddlefast->next->next;
    }
    /*保存中间节点的位置,中间节点的前继指向空,分隔为两个链表*/
    ListNode *part2 = new ListNode(0);
    part2 = pmiddle->next;
    pmiddle->next = NULL;
    /*2.对前后两部分列表进行排序*/
    ListNode *pfront = sortList(head);
    ListNode *prear = sortList(part2);
    /*3.合并两个有序链表*/
    ListNode *pnewhead = new ListNode(0);
    ListNode *pnew = pnewhead;
    while((pfront != NULL) && (prear != NULL))
    {
        if(pfront->val < prear->val)
        {
            pnew->next = pfront;
            pfront = pfront->next;
        }
        else
        {
            pnew->next = prear;
            prear = prear->next;
        }
        pnew = pnew->next;
        
    }
    while(pfront != NULL)
    {
        pnew->next = pfront;
        pnew = pnew->next;
        pfront = pfront->next;
    }
    while(prear != NULL)
    {
        pnew->next = prear;
        pnew = pnew->next;
        prear = prear->next;
    }
    /*注意最后节点指向空*/
    pnew->next = NULL;
    return pnewhead->next;
}

猜你喜欢

转载自blog.csdn.net/syc233588377/article/details/85320112