题目:Sort a linked list in O(n log n) time using constant space complexity.
题意及分析:要求使用o(nlogn)的时间复杂度和o(1)的空间复杂度将链表排序。o(nlogn)的排序算法有快速排序,归并排序和堆排序。但是快速排序最差情况下时间复杂度为o(n^2),所以不考虑,堆排序比较复杂,因此我这里使用归并排序。对于一个数组来说,归并排序主要是讲数组从中间分割成两部分,然后对左右子数组做同样操作,直至每个子数组都只有一个元素,然后两两合并。因为这里是链表,所以怎么找到中间分割点比较关键,这里使用两个指针slow,fast,slow每次移动一步,fast每次移动两步,当fast到链表尾时,slow所在位置就是链表中。我这里使用的是递归的方法求解。对于链表来说,非递归算法效率更高,所以合并处可以使用非递归算法,这样会快很多。
代码:
递归:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode sortList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode slow=head;
ListNode fast=head;
ListNode p=head;
while(fast!=null&&fast.next!=null){ //slow每次走一步,fast每次走两步,当fast走到最后时,slow走到链表的中间,这样就可以将链表分成两半
p=slow;
slow=slow.next;
fast=fast.next.next;
}
p.next=null; //将前半段链表设置为null结尾,这样链表就被分成(head,p),(slow,fast)
ListNode h1=sortList(head);
ListNode h2=sortList(slow);
return mergeList(h1, h2);
}
public ListNode mergeList(ListNode h1,ListNode h2){ //合并两个链表
if(h1==null) return h2;
if(h2==null) return h1;
if(h1.val<h2.val){
h1.next=mergeList(h1.next, h2);
return h1;
}else{
h2.next=mergeList(h1, h2.next);
return h2;
}
}
}
非递归:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode sortList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode slow=head;
ListNode fast=head;
ListNode p=head;
while(fast!=null&&fast.next!=null){ //slow每次走一步,fast每次走两步,当fast走到最后时,slow走到链表的中间,这样就可以将链表分成两半
p=slow;
slow=slow.next;
fast=fast.next.next;
}
p.next=null; //将前半段链表设置为null结尾,这样链表就被分成(head,p),(slow,fast)
ListNode h1=sortList(head);
ListNode h2=sortList(slow);
return mergeList(h1, h2);
}
public ListNode mergeList(ListNode h1,ListNode h2){ //合并两个链表
if(h1==null) return h2;
if(h2==null) return h1;
ListNode res = new ListNode(0); //结果链表
ListNode x=res;
while(h1!=null&&h2!=null){
if(h1.val<h2.val){
x.next=h1;
h1=h1.next;
x=x.next;
}else{
x.next=h2;
h2=h2.next;
x=x.next;
}
}
if(h1!=null)
x.next=h1;
if(h2!=null)
x.next=h2;
return res.next;
}
}