LeetCode OJ - Sort List

这道题的难点在于:

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     }

 

 

 

posted @ 2014-04-22 11:07  echoht  阅读(259)  评论(0编辑  收藏  举报