算法 - 合并多个排序链表

6 篇文章 0 订阅

1、题目描述

2、算法思想

2.1、暴力法

2.2、排序后相连

 可以用vector,也可以用list存储,一般情况下,如果不知道数据量有多少,用list的效率和内存使用上更优。

代码中采用的是list,list自带的sort的函数时间复杂度应该是O(nlogn)。

2.3、分治法

理论上,当 数据足够多时,分治法的时间复杂度是最优的。

3、代码实现

3.1、暴力法代码实现

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* new_list = new ListNode;

        std::vector<ListNode*>::iterator it = lists.begin();

        while(it != lists.end()){
            ListNode* list_head = (*it);

            new_list->next = mergeTwoLists(new_list->next, list_head);

            it++;
        }
        return new_list->next;
    }

    //合并两个链表
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* new_list = new ListNode;
        ListNode* re = new_list;

        while(l1 && l2)
        {
            if(l1->val < l2->val)   { new_list->next = l1; l1 = l1->next;}
            else                    { new_list->next = l2; l2 = l2->next;}
            
            new_list = new_list->next;
        }
        if(l1)  { new_list->next = l1;}
        if(l2)  { new_list->next = l2;}
        return re->next;    
    }
};

3.2、排序后相连法代码实现

//2-排序后相连O(kn*logkn) -- 48ms
bool cmp_less(const ListNode* la, const ListNode*lb)
{
    return (la->val < lb->val) ? true:false;
}

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        std::list<ListNode*> re_list;

        std::vector<ListNode*>::iterator it = lists.begin();
        while(it != lists.end()){
            ListNode* list_head = (*it);

            while(list_head)
            {
                re_list.push_back(list_head);
                list_head = list_head->next;
            }
            it++;
        }
        re_list.sort(cmp_less);

        ListNode* new_list = new ListNode;
        ListNode* re = new_list;
        std::list<ListNode*>::iterator it2 = re_list.begin();
        while(it2 != re_list.end()){
            new_list->next = *it2;
            new_list = new_list->next;
            it2++;
        }
        new_list->next = NULL;
        return re->next;
    }
};

3.3、分治法代码实现

//分治法 - 算法复杂度(O(kNLogk)) - 最优
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int list_len = lists.size();
        if(0 == list_len)       {return NULL;}
        else if(1 == list_len)  {return lists[0];}
        else if(2 == list_len)  {return mergeTwoLists(lists[0], lists[1]);}

        //开始拆分
        int mid = list_len/2;
        vector<ListNode*> list1;
        vector<ListNode*> list2;
        for(int i = 0;i<mid; i++)       {list1.push_back(lists[i]);}
        for(int i=mid;i<list_len;i++)   {list2.push_back(lists[i]);}

        ListNode* l1 = mergeKLists(list1);
        ListNode* l2 = mergeKLists(list2);

        return mergeTwoLists(l1,l2);
    }

    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) 
    {
        ListNode* new_list = new ListNode;
        ListNode* re = new_list;

        while(l1 && l2)
        {
            if(l1->val < l2->val)   { new_list->next = l1; l1 = l1->next;}
            else                    { new_list->next = l2; l2 = l2->next;}
            
            new_list = new_list->next;
        }
        if(l1)  { new_list->next = l1;}
        if(l2)  { new_list->next = l2;}
        return re->next;    
    }
};

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值