在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3 输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0 输出: -1->0->3->4->5
在常见排序算法中,只有归并排序和堆排序时间复杂度为O(nlgn)。在本题中,很明显是用归并排序。而在数组的归并排序中,是先将数组分半,分递归归并排序后,再合并的。在链表中,需要找到中点,将链表分为两段。
在之前的一题回文链表中,用到了findMiddle函数,但是在这里却行不通了。对于节点数为偶数的链表,会陷入死循环。为此,findMiddle中的快指针应指向第一个节点的后继,代码如下:
ListNode* findMiddle(ListNode* head)
{
if(head == nullptr || head->next == nullptr)
return head;
ListNode* fast = head->next, *slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
之后进行归并排序就很简单了,不要忘记将两段链表中间给断开。
ListNode* sortList(ListNode* head)
{
if (head == nullptr || head->next == nullptr)
return head;
//将链表分为first和second两段
ListNode* first = head;
ListNode* middle = findMiddle(head);
ListNode* second = middle->next;
middle->next = nullptr;
first = sortList(first);
second = sortList(second);
//归并,即合并两个有序链表
return mergeTwoLists(first, second);
}