转自
https://blog.csdn.net/u010853261/article/details/54884650
Question: 148. Sort List
Sort a linked list in O(n log n) time using constant space complexity.
中文:使用恒定的空间复杂度排序一个链表,要求时间复杂度是O(nlogn)
我们知道题目的要求是时间复杂度是O(nlogn), 很自然我们就想到了二路归并排序或则是快速排序。碎玉快速排序来说,设计到大量的精准索引定位,所以对于双链表来说更加适合,而这里是单链表,所以我选择二路归并排序。
现在我们这里需要用单链表实现,唯一的区别就是链表的分片,这里的分片我们选用的方法是双指针法,每次一个指针后移一位,另外一个后移两位。
/**
* 合并两个有序链表
* @param l1
* @param l2
* @return
*/
private static ListNode merge(ListNode l1, ListNode l2) {
ListNode l = new ListNode(0), p = l;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
p.next = l1;
l1 = l1.next;
} else {
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
if (l1 != null)
p.next = l1;
if (l2 != null)
p.next = l2;
return l.next;
}
/**
* 链表的二路归并排序
* @param head
* @return
*/
public static ListNode sortList(ListNode head) {
//空链表或则只有一个结点,直接返回head
if(head == null || head.next==null){
return head;
}
//1. 将list 切分为两个部分
ListNode prev=null, slow=head, fast=head;
while (fast !=null && fast.next !=null){
prev = slow;
slow = slow.next;//slow指针后移一个数据
fast = fast.next.next;//fast指针后移两个数据
}
prev.next = null;//将链表切断
//分别排序前后两个部分
ListNode l1 = sortList(head);
ListNode l2 = sortList(slow);
return merge(l1, l2);
}
测试用例:
public static void main(String[] args) {
ListNode head = new ListNode(0);
ListNode n1 = new ListNode(2);
ListNode n2 = new ListNode(4);
ListNode n3 = new ListNode(1);
ListNode n4 = new ListNode(3);
head.next = n1;
n1.next = n2;
n2.next=n3;
n3.next =n4;
ListNode h = sortList(head);
while (h!=null){
System.out.print(h.val + ",");
h = h.next;
}
}
运行结果:
0,1,2,3,4,