题意理解
对一个链表排序,要求时间复杂度O(nlogn)
问题分析
用归并 + 快慢指针
归并的套路是先分块排序,再合并排序。用快慢指针分块。
其他
https://blog.csdn.net/Scarlett_Guan/article/details/79435552
链接
ListNode* sortList(ListNode* head) {
if (!head || !head -> next) { //空链表或1个结点链表
return head; //直接返回链表
}
/*
ListNode* pp = head;
while (pp) {
cout << pp -> val;
pp = pp -> next;
}
cout << endl;
*/
ListNode *slow = head; //慢指针,初始化指向第一个结点
ListNode *fast = head; //快指针,初始化指向第一个结点
ListNode *pre = head; //指向慢指针前一个位置
while (fast && fast -> next) { //向后走两步,(已经判断可以走)
pre = slow; //保留慢指针前一个结点
slow = slow -> next; //慢指针走一步
fast = fast -> next -> next; //快指针走两步
}
pre -> next = nullptr; //慢指针来分隔
head = sortList (head); //递归排序前半链表
slow = sortList (slow); //递归排序后半链表
return mergeList (head, slow); //合并前后半个链表
}
ListNode* mergeList (ListNode* head1, ListNode* head2) {
ListNode* dummy = new ListNode(0); //虚拟头结点,方便合并(key)
ListNode* p = dummy; //后移指针
while (head1 && head2) { //链表双指针都存在
if (head1 -> val <= head2 -> val) { //前链表小
p -> next = head1; //前链表当前指针结点连上合并后的结点
head1 = head1 -> next; //前链表后移
}
else { //否则
p -> next = head2; //后链表当前指针结点连上合并和的结点
head2 = head2 -> next; //后链表后移
}
p = p -> next; //合并后的链表后移
}
if (head1) { //如果前链表还存在
p -> next = head1; //连上合并后的链表
}
if (head2) { //如果后链表还存在
p -> next = head2; //连上合并后的链表
}
return dummy -> next; //虚拟头结点去掉后的链表返回
}