归并排序是典型的分治算法思想:
划分子问题→求解子问题→合并子问题的解→得到原问题的解。
通过不断递归地将链表划分为两部分,直到不能划分为止,回溯时合并前后两段分别有序的链表,直到得到原始链表的有序状态,整个排序过程时间复杂度为 O(nlogn) 。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head==NULL || head->next==NULL) return head;
ListNode *fast=head,*slow=head;
//用快指针和慢指针找到链表中点
while(fast->next && fast->next->next){
fast=fast->next->next;
slow=slow->next;
}
//把链表分成两部分
fast=slow->next;
slow->next=NULL;
//排序左半部分
ListNode *l1=sortList(head);
//排序右半部分
ListNode *l2=sortList(fast);
//合并有序链表
return mergeTwoSortedList(l1,l2);
}
ListNode * mergeTwoSortedList(ListNode* l1,ListNode*l2){
ListNode dummy(-1);
ListNode * p=&dummy;
while(l1 && l2){
//从当前两个有序链表头中选择一个较小的节点链接至有序的链表中
if(l1->val<=l2->val){
p->next=l1;
l1=l1->next;
}else{
p->next=l2;
l2=l2->next;
}
p=p->next;
}
if(l1) p->next=l1;
if(l2) p->next=l2;
return dummy.next;
}
};