148. Sort List 链表排序

方法1:归并排序思路:

(1)设计一个寻找中间节点的函数;(2)设计一个归并两个已经有序的函数;(3) 主函数;

其中第一个函数思想:是在109题转换成BST当中使用的那样,同时也是快慢链表解决环形链表当中的设计一样的思路!

public class Solution {
    private ListNode findMidNode(ListNode head){
        ListNode slow = head;
        ListNode fast = head;
        while(fast.next != null && fast.next.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    private ListNode merge(ListNode head1, ListNode head2){
        ListNode dummy = new ListNode(0);
        ListNode index = dummy;
        while(head1 != null && head2 != null)
        {
            if(head1.val < head2.val)
              {
                  index.next = head1;
                  head1 = head1.next;
              }
             else
              {
                  index.next = head2;
                  head2 = head2.next;
              }
              index = index.next;
        }
        if(head1 != null)  index.next = head1;
        else               index.next = head2;
        return dummy.next;
    }
    public ListNode sortList(ListNode head) {
        if(head == null || head.next == null){
            return head;
        }
        ListNode mid = findMidNode(head);
        ListNode left = sortList(mid.next);
        mid.next = null;
        ListNode right = sortList(head);
        return merge(left,right);
    }
}

 思路2:利用快速排序思想!!!

首先,快速排序有两种,一种是三分,一种是二分。但是核心思想是一样的:每次为了一个元素,将整个矩阵或者链表,分成小于,等于,和大于三部分,或者小于等于,大于等于两部分。

二分的算法:

public class Quick
{
private static void sort(Comparable[] a, int lo,int hi)
{
    if (hi <= lo) return;
    int j = partition(a, lo, hi);
    sort(a, lo, j-1);
    sort(a, j+1, hi);
}
private static int partition(Comparable[] a, int lo, int hi)
{
   int i = lo;
   int j = hi +1;
   Comparable v = a[lo];
   while(true)
    {
        while(less(a[++i],v))  if(i == hi) break;
        while(less(v,a[--j]))  if(j == lo) break;
        if(i >= j) break;
        exch(a,i,j);
    }
   exch(a,lo,j);
   return j;
}
}

三分快排:

public class Quick3way
{
    private static void sort(Comparable[] a, int lo, int hi)
     {
       if(hi <= lo) return;
       int lt = lo, i = lo+1, gt = hi;
       Comparable v = a[lo];
       while(i <= gt)
          {
               int cmp = a[i].compareTo(v);
               if        (cmp < 0) exch(a,lt++,i++);
               else if (cmp > 0) exch(a,i,gt--);
               else                    i++;
          }
        sort(a, lo, lt-1);
        sort(a, gt+1, hi);
     }
}

同样的原理,可以使用三分快排的思想设计这个链表排序:

public class Solution {
    private ListNode findMidNode(ListNode head)
    {
        ListNode slow = head;
        ListNode fast = head;
        while(fast.next != null && fast.next.next != null)
        {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }
    public ListNode sortList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode mid = findMidNode(head);
        ListNode leftDummy = new ListNode(0), leftIndex = leftDummy;
        ListNode midDummy = new ListNode(0), midIndex = midDummy;
        ListNode rightDummy = new ListNode(0), rightIndex = rightDummy;
        while(head != null)
        {
            if(head.val < mid.val)
            {
                leftIndex.next = head;
                leftIndex = leftIndex.next;
            }
            else if(head.val > mid.val)
            {
                rightIndex.next = head;
                rightIndex = rightIndex.next;
            }
            else
            {
                midIndex.next = head;
                midIndex = midIndex.next;
            }
            head = head.next;
        }
        leftIndex.next = null;
        midIndex.next = null;
        rightIndex.next = null;
        ListNode left = sortList(leftDummy.next);
        ListNode right = sortList(rightDummy.next);
        return concat(left, midDummy.next, right);
    }
    private ListNode findTail(ListNode head)
    {
        if(head == null || head.next == null) return head;
        while(head.next != null)
        {
            head = head.next;
        }
        return head;
    }
    private ListNode concat(ListNode left, ListNode mid, ListNode right)
    {
        ListNode dummy = new ListNode(0), index = dummy;
        index.next = left; index = findTail(index);
        index.next = mid; index = findTail(index);
        index.next = right;
        return dummy.next;
    }
}

设计当中遇到的问题:(1)每次重新整合,都必须必须给列三个节点末尾赋值null,方便找tail;(2)注意函数是值传递:基本类型,和对象类型不一样!

posted @ 2016-04-16 15:12  ProWhalen  阅读(286)  评论(1)    收藏  举报