Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.


算法一:用multiset对节点排序,仅在第一次排序时花费O(k log(k))时间,后面每次更新一个节点费时 log(k)。时间复杂度O(n log(k)),n为所有节点数。 但测试效果不是很理想。


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
 
 class comp{
    public:
        bool operator()(ListNode *p, ListNode *q){ return p->val < q->val; } 
 };
 
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *head=NULL, *cur=head;
        
        multiset<ListNode*,comp> table;
        for(int i=0;i<lists.size();i++){
            if(lists[i]) table.insert(lists[i]);
        }
        
        ListNode *q;
        
        while(!table.empty()){
            multiset<ListNode*,comp>::iterator it = table.begin();
            if(head==NULL){ 
                head = *it; cur = head; 
                q = (*it)->next;
                table.erase(it);
                if(q) table.insert(q);
            }
            else{
                cur->next = *it; cur = cur->next;
                ListNode *q = (*it)->next;
                table.erase(it);   //cost log(k) time to erase the old node
                if(q) table.insert(q);  //add the next node, cost log(k) time to re-sort the node
            }
        }
        
        if(cur) cur->next = NULL;
        return head;
    }
};

算法二:multiset是用红黑树实现的,其实用堆就够了。priority_queue用堆实现,但效率并没有提高多少。数据结构上已无法再改进,只能从算法上改进。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
 
 class comp{
    public:
        bool operator()(ListNode *p, ListNode *q){ return p->val > q->val; } 
 };
 
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *head=NULL, *cur=head;
        
        priority_queue<ListNode*,vector<ListNode*>,comp> table;
        for(int i=0;i<lists.size();i++){
            if(lists[i]) table.push(lists[i]);
        }
        
        ListNode *q;
        
        while(!table.empty()){
            
            q = table.top();
            table.pop();
            
            if(head==NULL){ 
                head = q; cur = head; 
            }
            
            else{
                cur->next = q; cur = cur->next;
            }
            
            q = q->next;
            if(q) table.push(q);  //add the next node, cost log(n) time to re-sort the node
            
        }
        
        if(cur) cur->next = NULL;
        return head;
    }
};

算法三: 用分治思想。 但从AC通过时间来看似乎仍然没有提高什么效率。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
 
 class comp{
    public:
        bool operator()(ListNode *p, ListNode *q){ return p->val > q->val; } 
 };
 
class Solution {
public:
    ListNode* merge2Lists(ListNode* L1, ListNode* L2){
        
        if(L1==NULL) return L2;
        else if(L2==NULL) return L1;
        ListNode *head = NULL, *cur = head;
        if(L1->val <= L2->val){ head = cur = L1; L1 = L1->next; }
        else{ head = cur = L2; L2 = L2->next; }
        while(L1 && L2){
            if(L1->val <= L2->val){ cur->next = L1; cur = cur->next; L1 = L1->next; }
            else{ cur->next = L2; cur = cur->next; L2 = L2->next; }
        }
        if(L1) cur->next = L1;
        else cur->next = L2;
        return head;
        
    }
    
    ListNode* mergeKLists(vector<ListNode*>& lists,int p,int r) {
        if(p>r) return NULL;
        if(p==r) return lists[p];
        if(p==r-1) return merge2Lists(lists[p],lists[r]);
        
        ListNode *L1 = mergeKLists(lists,p,(p+r)/2);
        ListNode *L2 = mergeKLists(lists,(p+r)/2 + 1, r);
        return merge2Lists(L1,L2);
    }
    
    ListNode* mergeKLists(vector<ListNode*>& lists) {
    
        if(lists.empty()) return NULL;
        return mergeKLists(lists,0,lists.size()-1);
    }
};


PS: 在AC time统计图看到三个算法时间都挺靠后的。但理论上来讲时间复杂度下限应该是O(n log(k)),再将别人的AC代码测试发现效果相差不大,都在400ms左右,但统计表上显示有50ms 的C++测试,似乎还有更好的算法???或者是后面又增加了测试用例??

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值