LintCode 98-链表排序

本人电子系,只为一学生。心喜计算机,小编以怡情。


在 O(n log n) 时间复杂度和常数级的空间复杂度下给链表排序。

样例
给出 1->3->2->null,给它排序变成 1->2->3->null.


感悟:要求 O(n log n) 时间复杂度,然后我上网查了一下别的博主的博客的前言,发现只能用并归排序来做,我又查了一下并归排序,然后写出了之后的又臭又长的代码。不过用链表来做排序,那真是超级酸爽。。。


思路:我是以1,2,4,8…….为并归的单位

public ListNode sortList(ListNode head) {  
        // write your code here
        if(head==null||head.next==null) return head;

        int len=getlength(head);//得到长度

        ListNode realhead=new ListNode(0);//人为的加一个头结点
        realhead.next=head;

        ListNode flag=realhead;//为了不每次都从头开始查找
        //我们定义一个flag,比如132null,当并归2与null时,flag指向3

        for(int i=1;i<len;i*=2)//外层控制总次数1,2,4,8,....
        {
            flag=realhead;
            ListNode pre=flag.next;
            ListNode last=flag;
            //内层是分别的2,4,8,16
            while(last!=null)
            {
            int count=i;
            pre=flag.next;
            last=pre;
            while(last!=null&&count--!=0)
            {
                last=last.next;
            }//last指向要并归的片段首部,比如12345,长度为2时的片段
            //pre指向1,last指向3

            //因为等会要切成片,会丢失关系,因此给5做个引用,使链表能够恢复
            ListNode a=flag;
            int linshi=i*2+1;
            while(a!=null&&linshi--!=0)
                a=a.next;
            //
            //切片
            slash(pre, i);
            slash(last, i);
            //after slash we need reconnect;
            ListNode temp=merge(pre, last);//整合切片
            flag.next=temp;让flag指向头部,这样联系就建立起来了
            //flag de dingwei
            count=2*i;
            while(flag!=null&&count--!=0)
            {
                flag=flag.next;
            }//移动flag,这样不用每次都从头部找东西了,此例flag指向4
            //再将联系按上
            if (flag==null) {//flag可能出现null情况
                break;
            }
            flag.next=a;//让4指向5,切片断掉的联系就连上了
            }
        }
        return realhead.next;
    }

     //将两个以null结尾的链表整合到一个并返回头部
    static ListNode merge(ListNode head,ListNode last)
    {
        if(last==null) return head;
        if(head==null) return last;
        ListNode ret=head;//fanhui xiaozhi

        ListNode temphead=new ListNode(0);
        temphead.next=head;
        ListNode pre=temphead;

        while(last!=null)
        {
            ListNode temp2=last.next;
            while(pre.next!=null&&pre.next.val<last.val)
            {
                pre=pre.next;
            }

            ListNode t=pre.next;
            pre.next=last;
            last.next=t;
            last=temp2;
        }
        return temphead.next;
    }

    //将链表以1,2,4.。。。等单位划分为小片(用于并归排序)
    //就是将最后一个元素.next=null
    static  void slash(ListNode head,int count)
    {
        while(head!=null&&--count!=0)
        {
            head=head.next;
        }
        if(head!=null)
        head.next=null;
    }

    static int getlength(ListNode head)//获得链表长度函数
    {
        int count=0;
        while(head!=null)
        {
            count++;
            head=head.next;
        }
        return count;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值