• LeetCode OJ


    这道题的难点在于:

    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     }
    有问题可以和我联系,bettyting2010#163 dot com
  • 相关阅读:
    装饰模式
    You can't specify target table 'a' for update in FROM clause
    Spring事务知识点
    JAVA中的volatile关键字
    验证HashSet和HashMap不是线程安全
    ZYNQ7000 通过FPGA Manager加载比特流
    verilog中可综合的task使用
    verilog条件编译
    Vivado debug异常现象
    Matlab相关函数使用
  • 原文地址:https://www.cnblogs.com/echoht/p/3680038.html
Copyright © 2020-2023  润新知