leetcode Sort List

sort list: https://leetcode.com/problems/sort-list/


数组的排序比较相对于链表的,还是比较容易的。链表的排序,有一个最麻烦的地方就是,无法通过下标来访问节点,所以操作起来就没有数组那么方便。

链表排序,拿到这题,第一个想到的是快排。快排的思路和数组的一模一样,只不过要多两个list指针,一个指向比较节点的left, 一个指向比较节点的right。从左往右遍历整个链表就可以了,快排过一次的链表,比较节点的位置都是正确地,然后用递归,排左边和右边,虽然有点麻烦,但还可以,思路比较简单。

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        return sort(head, 0);
    }
    ListNode* sort(ListNode* head, ListNode* end)
    {   if(head == end)
            return head;
        ListNode* saveHead = head;
        ListNode* preHead = NULL;
        ListNode* lList = head;
        ListNode* rList = head;
        head=head->next;
        while(head!= end ){
            if(head->val > saveHead->val){
                rList->next = head;
                rList = rList->next;
                head = head->next;
            }
            else{
                ListNode* temphead = head->next;
                head->next = lList;
                lList= head;
                head = temphead;
                if(!preHead)
                    preHead = lList;
            }
        }
        rList->next =end;
        if(preHead != NULL)
            {
                preHead->next = saveHead;
               lList = sort(lList, saveHead);
            }
        saveHead->next = sort(saveHead->next, end);
        return lList;
    }
};

这个结果,Time Limit Exceeded

简直了,用的例子是节点的数字只有1,2,3,然后有几百个节点。快排的弊端,最坏情况下o(n2)的时间复杂度,马上体现出来了……


没办法,只有用归并排序了。归并的话最坏都是O(nlogn)的。

归并的话主要思路:首先,要把整个List,分成两个List,然后各自排序,在进行归并算法。两个子List,排序也是用归并,这里面的采用递归的方法。对子链表一直归并,知道子链表无法再分成两个链表为止。和数组的归并算法是一样的,只是数组的归并算法采用下表的方法来吧数组分成两个小数组,而链表,是真正把整个链表分开的。

这里主要用到两个子函数,split是把链表分成两个子链表,而merge是把两个有序链表进行归并排序。


class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head==0 || head->next==0)
            return head;
        ListNode* mid = split(head);
        return merge(sortList(head), sortList(mid));
    }
    
    ListNode* merge(ListNode* start1, ListNode* start2)
    {
        ListNode* head = 0;
        if(start2 == 0)
            return start1;
        if(start1->val < start2->val)
            {
                head = start1;
                start1 = start1->next;
            }
        else {
            head = start2;
            start2 = start2->next;
        }
        ListNode* tempList = head;
        while(start1!= 0 && start2 != 0){
            if(start1->val > start2->val){
                tempList->next = start2;
                start2 = start2->next;
                tempList = tempList->next;
            }
            else{
                tempList->next = start1;
                start1 = start1->next;
                tempList = tempList->next;
            } 
        }
        if(start1 == 0)
            tempList->next = start2;
        else 
            tempList->next = start1;
        return head;
    }
    
    ListNode* split(ListNode* head){
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast!= 0 && fast->next != 0 && fast->next->next !=0)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        ListNode* midList = slow->next;
        slow->next =0;
        return midList;
        
    }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值