在 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;
}