题目
思路一 自顶向下归并排序
找到链表中点,以中点为分界,把链表拆分为两个子链表,寻找链表的中点用快慢指针的做法。对两个子链表分别排序,再将排序后的子链表合并。
代码一
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head == nullptr || head -> next == nullptr)
return head;
ListNode *slow = head, *fast = head -> next;
while(fast && fast -> next){
slow = slow -> next;
fast = fast -> next -> next;
}
ListNode* mid = slow -> next;
slow -> next = nullptr;
return merge(sortList(head), sortList(mid));
}
ListNode* merge(ListNode* a, ListNode* b){
ListNode* dummy = new ListNode();
ListNode* head = dummy;
while(a && b){
if(a -> val <= b -> val){
head -> next = a;
a = a -> next;
}else{
head -> next = b;
b = b -> next;
}
head = head -> next;
}
if(a) head -> next = a;
else head -> next = b;
return dummy -> next;
}
};
思路二 自底向上归并排序
先找到链表长度,再从长度1开始合并子链表,每次合并指定长度的链表需要使用一个节点记录链表的开头,再分别找到要合并链表的开头,并记录下一个以此长度合并链表的指针。
代码二
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head == nullptr || head -> next == nullptr) return head;
int len = 0;
ListNode* node = head;
while(node != nullptr){
len++;
node = node -> next;
}
ListNode* dummy = new ListNode(0,head);
for(int subLen = 1; subLen < len; subLen <<= 1){
ListNode *pre = dummy, *cur = dummy -> next;
while(cur){
ListNode* h1 = cur;
for(int i = 1; i < subLen && cur -> next; i++)
cur = cur -> next;
ListNode* h2 = cur -> next;
cur -> next = nullptr;
cur = h2;
for(int i = 1; i < subLen && cur && cur -> next; i++)
cur = cur -> next;
ListNode* next = nullptr;
if(cur != nullptr){
next = cur -> next;
cur -> next = nullptr;
}
ListNode* merged = merge(h1, h2);
pre -> next = merged;
while(pre -> next)
pre = pre -> next;
cur = next;
}
}
return dummy -> next;
}
ListNode* merge(ListNode* a, ListNode* b){
ListNode* dummy = new ListNode();
ListNode* head = dummy;
while(a && b){
if(a -> val <= b -> val){
head -> next = a;
a = a -> next;
}else{
head -> next = b;
b = b -> next;
}
head = head -> next;
}
if(a) head -> next = a;
else head -> next = b;
return dummy -> next;
}
};