單鏈表的歸併排序
阿新 • • 發佈:2019-01-23
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,