题目
Sort a linked list in O(n log n)
time using constant space complexity.
分析
由于要求O(nlgn)的时间复杂度,自然就是归并排序、堆排序、快速排序;但是,还要求了O(1)空间复杂度。
如果递归不算空间的话,可以采用递归的归并排序。
如果使用非递归的归并排序,由于是单向链表,没法像数组那样直接指定元素位置,会导致时间复杂度达到O(n^2)。
堆排序用单向链表很困难。
快速排序由于最坏时间复杂度会是O(n^2),不靠谱,这里使用单向链表快速排序测试,会TLE。
代码
public class SortList { class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } } public ListNode sortList(ListNode head) { // return mergeSort(head); if (head == null || head.next == null) { return head; } ListNode tail = head; while (tail.next != null) { tail = tail.next; } return quickSort(head, tail); } private ListNode quickSort(ListNode head, ListNode tail) { if (head == null || tail == null || head.equals(tail)) { return head; } ListNode p = head; ListNode q = head.next; ListNode pPre = head; while (q != null && !q.equals(tail.next)) { if (q.val <= head.val) { pPre = p; p = p.next; swap(p, q); } q = q.next; } swap(head, p); quickSort(head, pPre); quickSort(p.next, tail); return head; } private void swap(ListNode ln1, ListNode ln2) { int temp = ln1.val; ln1.val = ln2.val; ln2.val = temp; } private ListNode mergeSort(ListNode head) { if (head == null || head.next == null) { return head; } // find the mid node, and split to two lists ListNode p = head; ListNode q = head; ListNode pPre = p; while (q != null && q.next != null) { pPre = p; p = p.next; q = q.next.next; } pPre.next = null; // split // divide and conquer ListNode l1 = mergeSort(head); ListNode l2 = mergeSort(p); // merge return merge(l1, l2); } private ListNode merge(ListNode l1, ListNode l2) { ListNode guard = new ListNode(0); // guard ListNode tail = guard; while (l1 != null && l2 != null) { if (l1.val < l2.val) { tail.next = l1; l1 = l1.next; } else { tail.next = l2; l2 = l2.next; } tail = tail.next; } if (l1 != null) { tail.next = l1; } else { tail.next = l2; } return guard.next; } }