链表排序问题(leetcode试题)

题目描述:Sort a linked list in O(n log n) time using constant space complexity.

问题分析

时间复杂度为O(nlogn)的排序算法一般有快速排序和归并排序两种。通常情况下快速排序适用于数组,基于链表的快速排序要重新设计指针扫描方案。而自底向上的归并排序本身比较适合与链表。

快速排序

参考http://blog.csdn.net/otuhacker/article/details/10366563的方法,博主给出的是cpp,此处附上Java代码

public class QuickSort 
{
    public static ListNode sortList(ListNode head)
    {
        sortList(head,null);
        return head;
    }
    private static void sortList(ListNode h,ListNode e)
    {
        if(h==e) return;
        ListNode mid=partition(h,e);
        sortList(h,mid);
        sortList(mid.next,e);
    }
    private static ListNode partition(ListNode h,ListNode e)//切分
    {
        int k=h.val;
        ListNode i=h,j=h.next;
        while(j!=e)
        {
            if(j.val<k)
            {
                i=i.next;
                exch(i,j);
            }
            j=j.next;
        }
        exch(h,i);
        return i;
    }
    private static void exch(ListNode i,ListNode j)
    {
        int temp=j.val;
        j.val=i.val;
        i.val=temp;
    }
}

归并排序

自底向上的归并排序只需要重新组织链表链接就能将链表原地排序
java版本1

public class MergeSort { // 归并排序
    public static ListNode sortList(ListNode head)//自底而上
    {
        int N=0;
        for(ListNode k=head;k!=null;k=k.next) N++;
        ListNode p=new ListNode(0);
        p.next=head;
        ListNode h=p;
        for(int sz=1;sz<N;sz=sz+sz)
        {
            p=h;
            while(p.next!=null)
            {
                p =merge(p, sz);
            }
        }
        return h.next;
    }
    private static ListNode merge(ListNode p,int sz)
    {
        int c=0;
        ListNode i=p,j=p;
        for(int k=0;k<sz&&j.next!=null;k++)
            j=j.next;
        ListNode m=j;
        while(true)
        {
            if(c>=sz||j.next==null) break;
            if(i==m){j=j.next;c++;continue;}
            if(i.next.val<=j.next.val)
                i=i.next;
            else
            {
                insert(i, j);
                c++;
            }
        }
        return j;
    }
    private static void insert(ListNode i,ListNode j)
    {
        ListNode k=j.next;
        j.next=j.next.next;
        k.next=i.next;
        i.next=k;
        i=k.next;
    }
}

leetcode 自上而下代码

public class Solution {
    public ListNode sortList(ListNode head) {
        if (head == null || head.next == null)
            return head;
        ListNode slow = head;
        ListNode fast = head.next;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode right = sortList(slow.next);
        slow.next = null;
        ListNode left = sortList(head);
        // /待左右两边各自有序,进行归并即可
        ListNode temp_head = new ListNode(0);
        ListNode temp_node = temp_head;
        while (left != null && right != null) {
            if (left.val < right.val) {
                temp_node.next = left;
                left = left.next;
            } else {
                temp_node.next = right;
                right = right.next;
            }
            temp_node = temp_node.next;
        }
        if (left != null)
            temp_node.next = left;
        if (right != null)
            temp_node.next = right;
        return temp_head.next;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值