对链表进行归并排序,主体思想是对链表进行分割,然后对分割后的两部分分别排序,最后对这两部分进行合并,需要注意的点有
1,对链表进行分割,寻找分割点可以使用快慢指针,设置慢指针p,快指针q,p每次走一步,q每次走两步,那么当q到达链表末尾时,p此时指向链表中点附近,因此以p作为分割点。
2,对两个链表进行合并排序,使用递归的方式会非常简洁并且易于理解。
代码如下
class Solution {
public ListNode sortList(ListNode head) {
return mergeSort(head);
}
public ListNode mergeSort(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode p = head;
ListNode q = head;
ListNode prep = head;
while (q != null && q.next != null) {
prep = p;
p = p.next;
q = q.next.next;
}
prep.next = null;
ListNode h1 = mergeSort(head);
ListNode h2 = mergeSort(p);
return merge(h1,h2);
}
public ListNode merge(ListNode p,ListNode q) {
if(p == null && q == null) {
return null;
} else if(p == null) {
return q;
} else if(q == null) {
return p;
} else {
if(p.val < q.val) {
p.next = merge(p.next,q);
return p;
} else {
q.next = merge(p,q.next);
return q;
}
}
}
}
/**
class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
**/