• [Leetcode] Merge k sorted lists 合并k个已排序的链表


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

     思路:这题最容易想到的是,(假设有k个链表)链表1、2合并,然后其结果12和3合并,以此类推,最后是123--k-1和k合并。至于两链表合并的过程见merge two sorted lists的分析。复杂度的分析见JustDoIT的博客。算法复杂度:假设每个链表的平均长度是n,则1、2合并,遍历2n个节点;12结果和3合并,遍历3n个节点;....123...k-1的结果和k合并,遍历kn个节点,总共遍历n(2+3+4+....k)=n*(k^2+k-2)/2,因此时间复杂度是O(n*(k^2+k-2)/2)=O(nk^2)。     其次,可以想到用分治的思想,两两合并直至最后。

    针对方法一,

     1 class Solution {
     2 public:
     3     //用向量存储链表
     4     ListNode *mergeKLists(vector<ListNode *> &lists) 
     5     {
     6         if(lists.size()==0) return NULL;
     7         ListNode *res=lists[0];     //取出第一个链表
     8         for(int i=1;i<lists.size();i++)     //反复调用
     9             res=mergeTwoList(res,lists[i]);
    10 
    11         return res;    
    12     }
    13 
    14     //归并排序
    15     ListNode *mergeTwoList(ListNode *head1,ListNode *head2)
    16     {
    17         ListNode node(0);   //创建头结点的前置结点
    18         ListNode *res=&node;
    19         while(head1&&head2)
    20         {
    21             if(head1->val<=head2->val)
    22             {
    23                 res->next=head1;
    24                 head1=head1->next;
    25             }
    26             else
    27             {
    28                 res->next=head2;
    29                 head2=head2->next;
    30             }
    31             res=res->next;
    32         }
    33 
    34         if(head1)
    35             res->next=head1;
    36         else if(head2)
    37             res->next=head2;
    38         
    39         return node.next;
    40     }
    41 };

    针对方法二:比较难想的是,两两合并时,链表的选取。

     1 /**
     2  * Definition for singly-linked list.
     3  * struct ListNode {
     4  *     int val;
     5  *     ListNode *next;
     6  *     ListNode(int x) : val(x), next(NULL) {}
     7  * };
     8  */
     9 class Solution {
    10 public:
    11     ListNode *mergeKLists(vector<ListNode *> &lists) 
    12     {
    13         int len=lists.size();
    14         if(len==0)
    15             return NULL;
    16 
    17         while(len>1)
    18         {
    19             int k=(len+1)>>1;
    20 
    21             for(int i=0;i<len/2;++i)
    22             {
    23                 lists[i]=mergeTwoLists(lists[i],lists[i+k]);
    24             }
    25             len=k;
    26         }    
    27         return lists[0];
    28     }
    29 
    30     ListNode *mergeTwoLists(ListNode *head1,ListNode *head2)
    31     {
    32         ListNode *nList=new ListNode(-1);
    33         nList->next=head1;
    34         ListNode *pre=nList;
    35 
    36         while(head1&&head2)
    37         {
    38             if(head1->val >head2->val)
    39             {
    40                 pre->next=head2;
    41                 head2=head2->next;
    42             }
    43             else
    44             {
    45                 pre->next=head1;
    46                 head1=head1->next;
    47             }
    48             pre=pre->next;
    49         }
    50 
    51         if(head1)
    52         {
    53             pre->next=head1;
    54         }
    55         else   
    56             pre->next=head2;
    57 
    58         return nList->next;    
    59     }
    60 };

    还有一种方法是最小堆的方法,维护一个大小为k的最小堆,初始化堆中的元素为每个链表的表头,它们会自动排好序,然后取出其中的最小元素介入新的链表中,然后,将最小元素的后继压入堆中,下次再从堆中选取最小的元素。元素加入堆中的复杂度为O(longk),总共有kn个元素加入堆中,因此,复杂度也和算法2一样是O(nklogk)。具体代码如下:

     1 class Solution 
     2 {
     3 private:
     4 struct cmp
     5 {
     6     bool operator()(const ListNode *a,const ListNode *b)
     7     {
     8         return a->val >b->val;
     9     }
    10 }
    11 public:
    12     //用向量存储链表
    13     ListNode *mergeKLists(vector<ListNode *> &lists) 
    14     {
    15         int n=lists.size();
    16         if (n==0) return NULL;
    17 
    18         ListNode node(0);
    19         ListNode *res=&node;
    20 
    21         priority_queue<ListNode*,vector<ListNode*>,cmp> que;
    22 
    23         for(int i=0;i<n;i++)
    24         {
    25             if(lists[i])
    26                 que.push(list[i]);
    27         }
    28 
    29         while(! que.empty())
    30         {
    31             ListNode *p=que.top();
    32             que.pop();
    33             res->next=p;
    34             res=p;
    35 
    36             if(p->next)
    37                 que.push(p->next);
    38         }
    39 
    40         return node.next;
    41     }
    42 }

    此篇中,有很多分析过程都是来自JustDoITGrandyang的博客。

  • 相关阅读:
    StrUtils
    WebUtil
    TreeUtil
    SQL解决表结构不同的数据同步方案
    MongoDB还原备份Bson文件及导出SQL文件
    Tengine安装步骤
    C++_练习—多态_virtual
    C++_练习—this指针
    C++_练习—继承_构造初始化列表
    C++_练习—继承_构造析构
  • 原文地址:https://www.cnblogs.com/love-yh/p/7050404.html
Copyright © 2020-2023  润新知