C++ 合并k排序表的复杂性

C++ 合并k排序表的复杂性,c++,algorithm,C++,Algorithm,问题是将k个排序列表合并为一个排序列表。 我已经完成了三种解决方案。 首先是二分法,如下所示: ListNode* mergeKLists(vector<ListNode*>& lists) { if(lists.size()==0) return NULL; return mergeKLists(lists,0,lists.size()-1); } ListNode* mergeKLists(vector<ListNode*>& li

问题是将k个排序列表合并为一个排序列表。 我已经完成了三种解决方案。 首先是二分法,如下所示:

ListNode* mergeKLists(vector<ListNode*>& lists) 
{
    if(lists.size()==0) return NULL;
    return mergeKLists(lists,0,lists.size()-1);
}

ListNode* mergeKLists(vector<ListNode*>& lists,int start,int end) 
{
    if(start==end) return lists[start];
    ListNode *l1=mergeKLists(lists,start,(start+end)/2);
    ListNode *l2=mergeKLists(lists,(start+end)/2+1,end);
    return merge2Lists(l1,l2);
}
static bool heapComp(ListNode* a, ListNode* b) {
        return a->val > b->val;
}
ListNode* mergeKLists(vector<ListNode*>& lists) { //make_heap
    ListNode head(0);
    ListNode *curNode = &head;
    vector<ListNode*> v;   
    for(int i =0; i<lists.size(); i++){
        if(lists[i]) v.push_back(lists[i]);
    }
    make_heap(v.begin(), v.end(), heapComp); //vector -> heap data strcture

    while(v.size()>0){
        curNode->next=v.front();
        pop_heap(v.begin(), v.end(), heapComp); 
        v.pop_back(); 
        curNode = curNode->next;
        if(curNode->next) {
            v.push_back(curNode->next); 
            push_heap(v.begin(), v.end(), heapComp);
        }
    }
    return head.next;
}
struct Node{
  ListNode* node;
  int length;
  Node(ListNode *n,int x){
      node=n;
      length=x;
  }
};
bool compare(Node l1,Node l2)
{
    return l1.length>l2.length;
}
ListNode* mergeKLists(vector<ListNode*>& lists) 
{
        vector<Node> newlists;
        if(lists.empty()) return NULL;
        for(int i=0;i<lists.size();i++)
            newlists.push_back(Node(lists[i],length(lists[i])));
        make_heap(newlists.begin(),newlists.end(),compare);
        while(newlists.size()!=1)
        {
            Node p=newlists.front();
            pop_heap (newlists.begin(),newlists.end(),compare);
            Node q=newlists.front();
            newlists.pop_back();
            pop_heap (newlists.begin(),newlists.end(),compare);
            newlists.pop_back();
            newlists.push_back(Node(merge2Lists(p.node,q.node),p.length+q.length));
            push_heap (newlists.begin(),newlists.end(),compare);
        }
        return newlists[0].node;
}
ListNode*mergeKLists(向量和列表)
{
if(lists.size()==0)返回NULL;
返回mergeKLists(lists,0,lists.size()-1);
}
ListNode*mergeKLists(向量和列表、整数开始、整数结束)
{
if(start==end)返回列表[start];
ListNode*l1=合并列表(列表,开始,(开始+结束)/2);
ListNode*l2=合并列表(列表,(开始+结束)/2+1,结束);
返回合并列表(l1、l2);
}
复杂度约为O(nklogk)=(2nk/2+4nk/4+……nk*k/k)

其次,使用heap,如下所示:

ListNode* mergeKLists(vector<ListNode*>& lists) 
{
    if(lists.size()==0) return NULL;
    return mergeKLists(lists,0,lists.size()-1);
}

ListNode* mergeKLists(vector<ListNode*>& lists,int start,int end) 
{
    if(start==end) return lists[start];
    ListNode *l1=mergeKLists(lists,start,(start+end)/2);
    ListNode *l2=mergeKLists(lists,(start+end)/2+1,end);
    return merge2Lists(l1,l2);
}
static bool heapComp(ListNode* a, ListNode* b) {
        return a->val > b->val;
}
ListNode* mergeKLists(vector<ListNode*>& lists) { //make_heap
    ListNode head(0);
    ListNode *curNode = &head;
    vector<ListNode*> v;   
    for(int i =0; i<lists.size(); i++){
        if(lists[i]) v.push_back(lists[i]);
    }
    make_heap(v.begin(), v.end(), heapComp); //vector -> heap data strcture

    while(v.size()>0){
        curNode->next=v.front();
        pop_heap(v.begin(), v.end(), heapComp); 
        v.pop_back(); 
        curNode = curNode->next;
        if(curNode->next) {
            v.push_back(curNode->next); 
            push_heap(v.begin(), v.end(), heapComp);
        }
    }
    return head.next;
}
struct Node{
  ListNode* node;
  int length;
  Node(ListNode *n,int x){
      node=n;
      length=x;
  }
};
bool compare(Node l1,Node l2)
{
    return l1.length>l2.length;
}
ListNode* mergeKLists(vector<ListNode*>& lists) 
{
        vector<Node> newlists;
        if(lists.empty()) return NULL;
        for(int i=0;i<lists.size();i++)
            newlists.push_back(Node(lists[i],length(lists[i])));
        make_heap(newlists.begin(),newlists.end(),compare);
        while(newlists.size()!=1)
        {
            Node p=newlists.front();
            pop_heap (newlists.begin(),newlists.end(),compare);
            Node q=newlists.front();
            newlists.pop_back();
            pop_heap (newlists.begin(),newlists.end(),compare);
            newlists.pop_back();
            newlists.push_back(Node(merge2Lists(p.node,q.node),p.length+q.length));
            push_heap (newlists.begin(),newlists.end(),compare);
        }
        return newlists[0].node;
}
static bool heapComp(ListNode*a,ListNode*b){
返回a->val>b->val;
}
ListNode*合并列表(向量和列表){//make\u heap
listnodehead(0);
ListNode*curNode=&head;
向量v;
对于(int i=0;i堆数据结构
而(v.size()>0){
curNode->next=v.front();
pop_堆(v.begin()、v.end()、heapComp);
v、 向后弹出();
curNode=curNode->next;
如果(curNode->next){
v、 向后推(curNode->next);
推送堆(v.begin()、v.end()、heapComp);
}
}
返回head.next;
}
复杂性大约是O(nklogk),因为refine heap需要logk,我们需要在nk次中这样做

第三种方法是我所困惑的。我采用了Haffman三的想法,每次我都会选择两个最短的列表并进行合并,如下所示:

ListNode* mergeKLists(vector<ListNode*>& lists) 
{
    if(lists.size()==0) return NULL;
    return mergeKLists(lists,0,lists.size()-1);
}

ListNode* mergeKLists(vector<ListNode*>& lists,int start,int end) 
{
    if(start==end) return lists[start];
    ListNode *l1=mergeKLists(lists,start,(start+end)/2);
    ListNode *l2=mergeKLists(lists,(start+end)/2+1,end);
    return merge2Lists(l1,l2);
}
static bool heapComp(ListNode* a, ListNode* b) {
        return a->val > b->val;
}
ListNode* mergeKLists(vector<ListNode*>& lists) { //make_heap
    ListNode head(0);
    ListNode *curNode = &head;
    vector<ListNode*> v;   
    for(int i =0; i<lists.size(); i++){
        if(lists[i]) v.push_back(lists[i]);
    }
    make_heap(v.begin(), v.end(), heapComp); //vector -> heap data strcture

    while(v.size()>0){
        curNode->next=v.front();
        pop_heap(v.begin(), v.end(), heapComp); 
        v.pop_back(); 
        curNode = curNode->next;
        if(curNode->next) {
            v.push_back(curNode->next); 
            push_heap(v.begin(), v.end(), heapComp);
        }
    }
    return head.next;
}
struct Node{
  ListNode* node;
  int length;
  Node(ListNode *n,int x){
      node=n;
      length=x;
  }
};
bool compare(Node l1,Node l2)
{
    return l1.length>l2.length;
}
ListNode* mergeKLists(vector<ListNode*>& lists) 
{
        vector<Node> newlists;
        if(lists.empty()) return NULL;
        for(int i=0;i<lists.size();i++)
            newlists.push_back(Node(lists[i],length(lists[i])));
        make_heap(newlists.begin(),newlists.end(),compare);
        while(newlists.size()!=1)
        {
            Node p=newlists.front();
            pop_heap (newlists.begin(),newlists.end(),compare);
            Node q=newlists.front();
            newlists.pop_back();
            pop_heap (newlists.begin(),newlists.end(),compare);
            newlists.pop_back();
            newlists.push_back(Node(merge2Lists(p.node,q.node),p.length+q.length));
            push_heap (newlists.begin(),newlists.end(),compare);
        }
        return newlists[0].node;
}
struct节点{
ListNode*节点;
整数长度;
节点(ListNode*n,int x){
节点=n;
长度=x;
}
};
布尔比较(节点l1、节点l2)
{
返回l1.length>l2.length;
}
ListNode*合并列表(向量和列表)
{
向量新列表;
if(lists.empty())返回NULL;

对于(int i=0;i这里有一个有用的youtube视频,可以分解合并排序算法的空间和时间复杂性:。这可能会帮助您进一步分解您的特定问题。常规合并(与您在合并排序中发现的相同)将是线性的。如果N较大,则合并排序的一般最坏情况应为O:(N log N)。您可以删除下界的常量和较低的指数顺序。k个排序列表的合并为O(n log k)。请参阅。@JimMischel wiki将输出大小作为n,这n等于此处的我的nk。