原题目:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
题解:
1分治
ListNode* merge2Lists(ListNode* l1, ListNode* l2){
if(l1!=nullptr && l2!=nullptr){
if(l1->val<l2->val){
l1->next = merge2Lists(l1->next,l2);
return l1;
}
else{
l2->next = merge2Lists(l1,l2->next);
return l2;
}
}
if(l1==nullptr){
return l2;
}
else{
return l1;
}
}
ListNode* mergeKLists(vector<ListNode*>& lists){
if(lists.empty()){
return nullptr;
}
ListNode* ls;
while(lists.size()>1){
ls = merge2Lists(lists[0],lists[1]);
lists.erase(lists.begin());
lists.erase(lists.begin());
lists.push_back(ls);
}
return lists[0];
}
130 / 130 test cases passed.
Runtime: 69 ms
2堆排序
static bool heapcomp(ListNode* a, ListNode* b){
return a->val > b->val;
}
ListNode* mergeKLists(vector<ListNode*>& lists){
ListNode* result = new ListNode(0);
ListNode* current = result;
vector<ListNode*> value_lists;
for(int i =0; i<lists.size(); i++){
if(lists[i]) value_lists.push_back(lists[i]);
}
make_heap(value_lists.begin(),value_lists.end(),heapcomp);
while(value_lists.size()){
current->next = value_lists.front();
pop_heap(value_lists.begin(),value_lists.end(),heapcomp);
value_lists.pop_back();
current = current->next;
if(current->next!=NULL){
value_lists.push_back(current->next);
push_heap(value_lists.begin(),value_lists.end(),heapcomp);
}
}
return result->next;
}
130 / 130 test cases passed.
Runtime: 39 ms
思路:
算法非原创,而是在leetcode的discuss里面的解。参考了几个解,认为这两个解比较好。
算法都是很经典的算法了,接下来分析下算法的复杂度。
第一种是分治算法,用队列代替迭代,设k个list,平均长度为n,每层要算kn次,层数为logk,因此算法复杂度为O(knlogk).
第二种是堆排序算法,在堆数组里第一个是值最大的元素,因此修改了一下比较规则,让值最小的节点出现在第一位。每取一个节点都要将该list重新放回数组,放回一次需要logk步,共要取kn个,因此算法复杂度是O(knlogk)