题目描述:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity
这道题可以利用mergeTwoLists来做,一种方法是将k个链表一个一个地归并,即需要k步。随着归并的次数越多,已经归并的链表会越来越长,所以效率比较差。在这道题的最后一个测试案例中,k很大,我用这种方法会导致超时。
所以应该尽量将归并次数减少,采用分治法就可以实现这个目标。即将原链表数组分成两个链表数组,分别进行归并,得到结果后再进行归并。而这两个链表数组同样也用分治的方法归并,那么可以减少归并的次数。
考虑依次归并的时间复杂度:两个链表归并的时间复杂度为O(n),n为两个链表的节点总数,即每次向总链表增加一个节点,都需要比较一次,所以一共比较O(n)次。从而归并k个链表时,令N为所有节点总数,平均每个链表长度为N/k,那么k步归并的时间复杂度为N/k*(2+3+4....+k)=O(kN)。
而对于分治法来说,分logk次分治,每次分治所有的节点都要参与归并,所以每次分治的时间复杂度为O(N),分治法的时间复杂度为O(Nlogk)。在k很大的情况下,相比依次归并的方法能够节省大量的运行时间。
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size()==0) return NULL;
else if(lists.size()==1) return lists[0];
ListNode* head=NULL;
int i=lists.size()/2-1;
int j=lists.size()-1;
vector<ListNode*> x;
vector<ListNode*> y;
for(int m=0;m<=i;m++) x.push_back(lists[m]);
for(int m=i+1;m<=j;m++) y.push_back(lists[m]);
return mergeTwoLists(mergeKLists(x),mergeKLists(y));
}
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* result=new ListNode(0);
ListNode* head=result;
if(l1==NULL&&l2==NULL) return NULL;
while(l1!=NULL||l2!=NULL)
{
ListNode* temp=new ListNode(0);
if(l1==NULL&&l2!=NULL)
{
temp->val=l2->val;
result->next=temp;
result=result->next;
l2=l2->next;
}
else if(l1!=NULL&&l2==NULL)
{
temp->val=l1->val;
result->next=temp;
result=result->next;
l1=l1->next;
}
else if(l1->val>l2->val)
{
temp->val=l2->val;
result->next=temp;
result=result->next;
l2=l2->next;
}
else
{
temp->val=l1->val;
result->next=temp;
result=result->next;
l1=l1->next;
}
}
return head->next;
}
};