题目:
题解:
- 大家就看看大佬的题解吧,我肯定没大佬讲的好。
算法伪代码:
current = dummy.next;
tail = dummy;
for (step = 1; step < length; step *= 2) {
while (current) {
// left->@->@->@->@->@->@->null
left = current;
// left->@->@->null right->@->@->@->@->null
right = cut(current, step); // 将 current 切掉前 step 个头切下来。
// left->@->@->null right->@->@->null current->@->@->null
current = cut(right, step); // 将 right 切掉前 step 个头切下来。
// dummy.next -> @->@->@->@->null,最后一个节点是 tail,始终记录
// ^
// tail
tail.next = merge(left, right);
while (tail->next) tail = tail->next; // 保持 tail 为尾部
}
}
题解代码如下:
class Solution {
public:
ListNode* sortList(ListNode* head) {
ListNode dummy(0);
dummy.next=head;
ListNode* p=head;
int length=0;
while(p){
length++;
p=p->next;
}
for(int size=1;size<length;size<<=1)
{
ListNode* cur=dummy.next;//每次归并cur都从head节点开始
ListNode* tail=&dummy;//tail主要用于连接每次归并后的链表
while(cur){
ListNode* left=cur;
ListNode* right=cut(left,size);//将left切断,这样left有size个节点了,此时的right为后半部分的链表头
cur=cut(right,size);//将right切断,这样right有size个节点了,此时的cur为后半部分的链表头
tail->next=merge(left,right);//合并right和left
while(tail->next){//保持tail为尾节点
tail=tail->next;
}
}
}
return dummy.next;
}
ListNode* cut(ListNode* head,int n)//将链表head的前n个节点切下来,然后返回后半部分的链表头
{
ListNode* p=head;
while(--n&&p){
p=p->next;
}
if(!p)return nullptr;
ListNode* next=p->next;
p->next=nullptr;
return next;
}
ListNode* merge(ListNode* l1,ListNode* l2)//合并两个有序链表
{
ListNode dummy(0);
ListNode* p=&dummy;
while(l1&&l2){
if(l1->val<l2->val){
p->next=l1;
p=l1;
l1=l1->next;
}
else{
p->next=l2;
p=l2;
l2=l2->next;
}
}
p->next=l1?l1:l2;
return dummy.next;
}
};
// 纯递归
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head || !head->next)
return head;
ListNode *fast = head->next, *slow = head;
while (fast && fast->next) {
fast = fast->next->next;
slow = slow->next;
}
// 右半段的头节点
ListNode* mid = slow->next;
// 切开,分成左半段和右半段
slow->next = nullptr;
// 自底向上:获得左右链表合并好的结果,然后进行合并就行了
ListNode *left = sortList(head), *right = sortList(mid);
return merge(left, right);
}
ListNode* merge(ListNode* l1, ListNode* l2) // 合并两个有序链表
{
if (!l1)
return l2;
if (!l2)
return l1;
ListNode* head;
if (l1->val <= l2->val) {
head = l1;
head->next = merge(l1->next, l2);
} else {
head = l2;
head->next = merge(l1, l2->next);
}
return head;
}
};