解题思路:
1.先分割:
寻找链表中点,将链表分成两个子链表,中点用快慢指针找,慢指针走一步,快指针走两步,慢指针到中点时,快指针到末尾,
2.再合并
对列表排序,合并两个排好序的列表
代码
/**
* 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) {
return depart(head, nullptr);//进入归并
}
//1.分割 分割截至的条件是当前链表长度为1.即头指针下一个节点是空
//处理归并排序问题,下面两种场景不需要分和操作
ListNode* depart(ListNode* head,ListNode* tail){
if(head == nullptr){ //第一种场景是头指针是否为空
return head;//返回此节点
}
if(head->next == tail){//第二种场景是头指针的下一个指针是否是尾部
head->next = nullptr;//尾部也指向为空,分割到只剩一个节点了
return head;//返回此节点
}
ListNode* slow = head,*fast = head;//定义快慢两个指针都指向头节点
while(fast != tail){//当快指针没有到尾部,就一直循环
slow = slow->next;//慢指针指向下一个
fast = fast->next;//快指针也指向下一个,
if(fast != tail){//判断快指针是否到末尾,因为存在奇数链表
fast = fast->next;//如果没到的话就再走一步
}
}
ListNode* mid = slow;
return merge(depart(head,mid),depart(mid,tail));//将链表分开的部分合并
}
//2.排序合并
ListNode* merge(ListNode* head1,ListNode* head2){
ListNode* dumyHead = new ListNode(0);//创建一个空链表
ListNode* temp = dumyHead, *temp1 = head1, *temp2 = head2;//用temp代替dumyHead,否则dumyHead一直会变,定义两个指针,
while(temp1 != nullptr && temp2 != nullptr){//左指针和右指针的数都不为空
if(temp1->val <= temp2->val){//左指针指向的值小于右指针的值
temp->next = temp1;//把左指针的地址放到新链表第一个位置
temp1 = temp1->next;//左指针向右走一步
}else{
temp->next = temp2;//否则把右指针的地址放到新链表第一个位置
temp2 = temp2->next;//右指针向右走一步
}
temp = temp->next;//左右序列都为空后,新列表指针向后走一步
}
if(temp1 != nullptr){//判断左序列是否为空
temp->next = temp1;//不为空把最后的一个地址放到新链表
}else if(temp2 != nullptr){//判断右序列是否为空
temp->next = temp2;//不为空把最后的一个地址放到新链表
}
return dumyHead->next;//最终返回排好序的新链表
}
};