您的位置:首页 > 其它

LeetCode - Sort List

2014-04-15 17:02 197 查看

作者:disappearedgod
文章出处:/article/3730067.html
时间: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++)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: