这道题的难点在于:
1. 对链表排序,这样就不能向访问数组一样随机访问里头的元素;
2. 题中要求时间复杂度为O(nlogn),且空间复杂度为O(1)
我们一般了解的是快排和归并可以达到这样的时间复杂度,但是快排对于链表操作显得比较复杂(其实归并对这个链表操作也很复杂),而通常的归并的空间复杂度又是O(n)。
后来看了有原地归并排序,其空间复杂度达到O(1),我使用inplace-bottom-Up Merge sort。程序调试了很久(中间有过放弃的念头,每次这个念头出现的时候,我就对自己说,说不定这个bug解决了程序就AC了,终于在最后的期待中看到了AC),主要是因为链表的操作和Java中一般的赋值是浅copy。
bottom-up merge sort 可参见:http://en.wikipedia.org/wiki/Merge_sort#Bottom-up_implementation
inplace merge sort 参考的是:http://www.cnblogs.com/daniagger/archive/2012/07/25/2608373.html
下面是AC代码:
1 /** 2 * 总入口 3 * @param head 4 * @return 5 */ 6 public ListNode sortList(ListNode head) { 7 ListNode pointer = head; 8 int len = 0; 9 if(head == null || head.next == null) 10 return head; 11 while(pointer!=null) 12 { 13 len++; 14 pointer = pointer.next; 15 } 16 return sort(head, len); 17 } 18 /** 19 * 进入自底向上归并排序 20 * @param head 21 * @param len 22 * @return 23 */ 24 private ListNode sort(ListNode head,int len) 25 { 26 int width = 1; 27 ListNode r = null; 28 for(width = 1;width<=len;width = 2*width) 29 { 30 ListNode left = head; 31 ListNode pLeft = null; 32 ListNode pmid = left, mid=left.next, end = null, endNext = null; 33 int cnt = 0; 34 for(left = head;left!=null;left =endNext) 35 { 36 pmid = left; 37 cnt = 0; 38 while(++cnt<width && pmid.next!=null) 39 { 40 pmid = pmid.next; 41 } 42 mid = pmid.next;//if pmid.next == null 则没有左子数组 43 if(mid == null) 44 break; 45 end = mid; 46 cnt = 0; 47 while(++cnt<width && end.next!=null) 48 { 49 end = end.next; 50 } 51 endNext = end.next; 52 ListNode l = bottomUpSort(pLeft,left,pmid,mid,end,endNext); 53 if(end.next!=endNext) 54 end = pmid; 55 if(l!=null) 56 { 57 r = l; 58 head = r; 59 } 60 pLeft = end; 61 } 62 } 63 if(r == null) 64 return head; 65 return r; 66 } 67 /** 68 * bottomUpSort 这个名字应该改成inPlaceSort更恰当 69 * @param pLeft left的前一个node指针,为null表示left为链表头 70 * @param left 当前左子数组的第一个指针 71 * @param pmid 当前左子数组的最后一个指针 72 * @param mid 当前右子数组的第一个指针 73 * @param end 当前有子数组的最后一个指针 74 * @param endNext end的next Node 75 */ 76 private ListNode bottomUpSort(ListNode pLeft, ListNode left, ListNode pmid, ListNode mid, ListNode end, ListNode endNext) 77 { 78 ListNode p1 = left, pp1 = pLeft ; 79 ListNode p2 = mid, pp2 = pmid ; 80 ListNode t = null; 81 //pp1 = (left.val <= mid.val) ? left: null; 82 while(p1!=p2 && p2!=endNext ) 83 { 84 while(p1!=pmid.next && p1.val<=p2.val ) 85 { 86 pp1 = p1; 87 p1 = p1.next; 88 } 89 if(p1 == mid) 90 break; 91 while(p2!= endNext && p2.val<=p1.val ) 92 { 93 pp2 = p2; 94 p2 = p2.next; 95 } 96 ListNode ln = exchange(pp1,p1,pp2,p2,pmid,mid); 97 if(ln != null) 98 t = ln; 99 //end = pmid; 100 mid = pmid.next; 101 } 102 end = pmid; 103 if(pLeft == null) 104 return t; 105 return null; 106 } 107 /** 108 * 把小的部分移到前面 之所以参数比较多,是为了链表更便捷的操作 109 * @param pp1 110 * @param p1 111 * @param pp2 112 * @param p2 113 * @param pmid 114 * @param mid 115 * @return 116 */ 117 private ListNode exchange( ListNode pp1,ListNode p1, ListNode pp2,ListNode p2, ListNode pmid, ListNode mid) 118 { 119 if(pp1 == null) 120 { 121 pp2.next = p1; 122 pmid.next = p2; 123 return mid; 124 } 125 pp1.next = mid; 126 pp2.next = p1; 127 pmid.next = p2; 128 return null; 129 }