[LeetCode]problem 148. Sort List

TAG

归并排序链表非递归归并排序

题目链接

方法

要在O(nlgn)完成排序,对象又是单向链表,应该是优先考虑归并排序(其实感觉快排也是可以的)。

按照LeetCode的说法,常数空间就是指非递归,迭代。所以如果采用归并,那就得用非递归版。

纠结了一会儿,觉得关键得用一个空的头部节点,这样才能方便交换。迭代版就是递归版的逆过程,从每个大小为1的块开始归并的排,注意把merge后的结果与尚未排序的结果连接起来。

逻辑见代码吧,感觉写得挺concise,easy-to-understand , 只是效率不算很高。有时间再好好学习下。

代码

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(head == nullptr) { return nullptr; }
        ListNode *dummyHead = new ListNode(0);
        dummyHead->next = head ;
        unsigned stepSize = 1 ;
        while(true)
        {
            ListNode *emptyH1 = dummyHead ; // `empty` means the head is not for visit .
            ListNode *emptyH2 = moveKSteps(dummyHead, stepSize);
            if(emptyH2 == nullptr) { break; } // merged ok
            while(emptyH1->next)
            {
                emptyH1 = merge(emptyH1, emptyH2, stepSize);
                emptyH2 = moveKSteps(emptyH1, stepSize);
                if(emptyH2 == nullptr){ break; } // at rear part , there may be no h2 ! must check !
            }
            stepSize *= 2;
        }
        head = dummyHead->next ;
        dummyHead->next = nullptr ;
        delete dummyHead;
        return head ;
    }
private :
    ListNode *moveKSteps(ListNode *ptr, unsigned nrStep)
    {
        while(ptr != nullptr && nrStep--)
        {
            ptr = ptr->next ;
        }
        return ptr ;
    }
    ListNode* merge(ListNode *emptyH1, ListNode *emptyH2, unsigned stepSize)
    {
        unsigned h1LeftStep = stepSize ,
                 h2LeftStep = stepSize ;
        ListNode *mergeListRear = emptyH1;
        ListNode *ptr1 = emptyH1->next ,
                 *ptr2 = emptyH2->next ;
        while(ptr1 && h1LeftStep && ptr2 && h2LeftStep)
        {
            if(ptr1->val < ptr2->val)
            {
                mergeListRear->next = ptr1 ;
                ptr1 = ptr1->next ;
                --h1LeftStep;
            }
            else
            {
                mergeListRear->next = ptr2;
                ptr2 = ptr2->next ;
                --h2LeftStep;
            }
            mergeListRear = mergeListRear->next ;
        }
        while(ptr1 && h1LeftStep)
        {
            mergeListRear->next = ptr1 ;
            ptr1 = ptr1->next;
            mergeListRear = mergeListRear->next ;
            --h1LeftStep;
        }
        while(ptr2 && h2LeftStep)
        {
            mergeListRear->next = ptr2 ;
            ptr2 = ptr2->next;
            mergeListRear = mergeListRear->next;
            --h2LeftStep;
        }
        // emptyH1 still is the merged list (empty) head
        // and mergeListRear points the rear of merged list 
        // we should connect it to the next part , just assign it's next as ptr2
        mergeListRear->next = ptr2 ;
        // and Now , mergeListRear is the empty start of next part
        return mergeListRear;
    }

};

后记

速度相比这么慢还有可能有系统的原因——要么是最近LeetCode刷的人太多爆了系统,要么test cases变了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值