Sort a linked list in O(n log n) time using constant space complexity.
思路:O(nlgn)的时间复杂度,那就是归并排序和快排, 快速排序:使用快排也行,就是每次利用头节点作为基准,将小于它的交换到链表左侧,大于它的放在右侧,最后把它换到中间某个位置,然后递归处理左侧和右侧。但是相对于归并来说,它的元素交换次数太多了,可能会超时。
那么就对一个链表进行归并排序。
知识点1:归并排序的整体思想,涉及递归
知识点2:找到一个链表的中间节点的方法,经典快慢指针的思路
知识点3:合并两个已排好序的链表为一个新的有序链表。
代码如下:
/**
* 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 head1 = head;
ListNode mid = getMid(head);
ListNode head2 = mid.next ;
mid.next = null;
head1 = sortList(head1);
head2 = sortList(head2);
return merge(head1,head2);
}
public ListNode getMid(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast.next!=null&&fast.next.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
public ListNode merge(ListNode p1,ListNode p2){
ListNode temp = new ListNode(-1);
ListNode p = temp;
while(p1!=null && p2!=null){
if(p1.val<p2.val){
p.next = p1;
p1 = p1.next;
}else{
p.next = p2;
p2 = p2.next;
}
p = p.next;
}
if(p1!=null){
p.next = p1;
}else{
p.next = p2;
}
return temp.next;
}
}
比较经典的题目,值得多看几遍。参考博客:http://blog.youkuaiyun.com/worldwindjp/article/details/18986737