LeetCode - Sort List

来源:互联网 发布:钱龙金典版软件 编辑:程序博客网 时间:2024/06/07 06:38

作者: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<j.val;    }

返回

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


0 0
原创粉丝点击