鏈表的歸併排序
對一個鏈表排序,要求時間複雜度O(NlogN),空間複雜度爲常量級。對於時間複雜度的選擇,比較容易想到用歸併排序或者快速排序,但是歸併排序的空間複雜度在O(N)。
對於數組的歸併排序確實需要開闢另一個數組作臨時存儲,對於鏈表其實可以少了這一步。只要用dummyHead給一個虛擬的頭結點就很好操作整個鏈表。剩下就是歸併排序的迭代實現和遞歸實現。於是在我一下午的操作下,還是選擇了遞歸實現。迭代實現真心不容易
主要解題步驟:
1、二路歸併的使用
2、鏈表的切割(通過快慢指針完成鏈表的對半切割)
3、dummyHead的使用(關鍵!)
最後leecode真的很喜歡快慢指針的題,幾乎每個鏈表都有快慢指針的應用
實現代碼
public ListNode sortList(ListNode head) {
if(head == null) {
return null;
}
if(head.next == null) {
return head;
}
ListNode pre = null;
ListNode slow = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
pre = slow;
slow = slow.next;
fast = fast.next.next;
}
pre.next = null;
ListNode left = sortList(head);
ListNode right = sortList(slow);
return Merge(left,right);
}
public ListNode Merge(ListNode left,ListNode right) {
ListNode head = new ListNode(0);
ListNode cur = head;
while(left != null && right != null) {
if(left.val < right.val) {
cur.next = left;
left = left.next;
cur = cur.next;
}else {
cur.next = right;
right = right.next;
cur = cur.next;
}
}
if(left != null) {
cur.next = left;
}
if(right != null) {
cur.next = right;
}
return head.next;
}