LeetCode - Sort List

作者:disappearedgod
文章出处:http://blog.csdn.net/disappearedgod/article/details/23771995
时间:2014-4-16

题目

Sort List

 

Sort a linked list in O(n log n) time using constant space complexity.

Java

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */public class Solution {
    public ListNode sortList(ListNode head) {

    }
 }

解题

破题

这里规定了时间复杂度,所以有些排序像插入排序、选择排序等这类时间复杂度上界为θ(n^2)的算法就不适合。


一般解法

链表的排序是用一个跳一步的walker和一个跳两步的runner来写的,我首先参照了Coder_Ganker的博客
http://blog.csdn.net/linhuanmars/article/details/21133949

思想(理论知识):

单链表的快速排序和数组的快速排序在基本细想上是一致的,以从小到大来排序单链表为例, 都是选择一个支点,然后把小于支点的元素放到左边,把大于支点的元素放到右边。
      但是,由于单链表不能像数组那样随机存储,和数组的快排序相比较,还是有一些需要注意的细节:
  • 支点的选取,由于不能随机访问第K个元素,因此每次选择支点时可以取待排序那部分链表的头指针
  • 遍历量表方式,由于不能从单链表的末尾向前遍历,因此使用两个指针分别向前向后遍历的策略实效
事实上,可以可以采用一趟遍历的方式将较小的元素放到单链表的左边。具体方法为:
  • 定义两个"指针"walker, runner,其中walker指单链表头结点,runner指向单链表头结点的下一个结点 runner = runner.next.next
  • 使用runner遍历单链表,每遇到一个比支点小的元素,就和walker进行数据交换,然后令walker=walker.next

java代码为
public class Solution {
    public ListNode sortList(ListNode head) {
        return mergeSort(head);
    }
    private ListNode mergeSort(ListNode head){
        if(head==null || head.next == null)
          return head;
        ListNode walker = head;
        ListNode runner = head;
        
        while(runner.next!=null && runner.next.next!=null){
            walker = walker.next;
            runner = runner.next.next;
        }
        ListNode head2 = walker.next;
        walker.next = null;
        ListNode head1 = head;
        head1 = mergeSort(head1);
        head2 = mergeSort(head2);
        return merge(head1,head2);
    }
    private ListNode merge(ListNode head1, ListNode head2){
        ListNode helper = new ListNode(0);//把栈空间算上的话还是需要O(logn)的空间的
        helper.next = head1;
        ListNode pre = helper;
        while(head1!=null && head2 != null ){
            if(head1.val < head2.val){
                head1= head1.next;
            }
            else{
                ListNode next = head2.next;
                head2.next = pre.next;
                pre.next = head2;
                head2 = next;
            }
            pre = pre.next;
        }
        if(head2!=null){
            pre.next = head2;
        }
        return helper.next;
    }
}


后记

抛开时间限制,练习一下写单链表排序,首先写一下插入排序
private ListNode insertSort(ListNode head){
        ListNode pre_base = head;
        ListNode  base = head;
        ListNode pre_cmp = head;
        ListNode cmp = head;
        ListNode next;
        if(head ==null || head.next ==null)
          return head;
        for( int i =0;base.next!=null; pre_base = base,base=head.next,i++){
            for(int j =i; j>0 && less(base,cmp);pre_cmp=cmp,cmp = cmp.next,j--)
            {   
                //exch(pre_base,base,pre_cmp,cmp);
                next = base.next;
                base.next = cmp.next;
                cmp.next = next;
                pre_base.next = cmp;
                pre_cmp.next = base;
            }
        }
        return head;
    }
    private void exch(ListNode pre_i,ListNode i,ListNode pre_j, ListNode j){
        ListNode next = i.next;
        i.next = j.next;
        j.next = next;
        pre_i.next = j;
        pre_j.next = i;
    }
    
    private boolean less(ListNode i,ListNode j){
        return i.val

返回

LeetCode Solution(持续更新,java>c++)


你可能感兴趣的:(链表,LeetCode)