您的位置:首页 > 编程语言 > C语言/C++

leetcode:Merge k Sorted Lists (建立堆)

2017-02-10 19:58 513 查看
Merge k sorted
linked lists and return it as one sorted list. Analyze and describe its complexity.


思路:

    将每个链表的表头元素取出来,建立一个小顶堆,因为k个链表中都排好序了,因此每次取堆顶的元素就是k个链表中的最小值,可以将其合并到合并链表中,再将这个元素的指针指向的下一个元素也加入到堆中,再调整堆,取出堆顶,合并链表。。。。以此类推,直到堆为空时,链表合并完毕。

    因为想练习建堆的过程,所以我没有用STL里的make_heap等方法,而是自己写的建堆函数。若想看用STL的建堆方法的,可以参考网上答案

    建堆的时间复杂度是k/2logk, 每次取出堆顶再加入元素的复杂度是logk,假设每条链表平均有n个元素,则一共有nk-k次。因此总的时间复杂度为O(nklogk)。

    还有一种思路是取出两条,用merge2Lists的方法合并为一条,再将这条和下一条用merge2Lists来合并为一条,以此类推。假设每条链表平均有n个元素,此种时间复杂度是O(2n+3n+…+kn), 为O(nk²),因此若用此法会超时。
/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.empty()) return NULL;
ListNode *newList=  new ListNode(0);
ListNode *r=newList;
int k=lists.size();
vector<ListNode*> heap;
for (int i = 0; i < k; ++i)
{
if(lists[i]) heap.push_back(lists[i]);
}

while(!heap.empty())
{
makeMinHeap(heap);

ListNode*p=new ListNode(heap[0]->val);
r->next=p;
r=p;

heap[0]=heap[0]->next;
if(!heap[0])
{
swap(heap[0],heap[heap.size()-1]);
heap.pop_back();//                        vector has no pop_front(),pay attention!!!!!!
}
}
return newList->next;

}

void minHeapfixdown(vector<ListNode*>& a,int i,int n){
int j,temp;
ListNode* ptemp=a[i];
temp=a[i]->val;
j=2*i+1;

while(j<n)
{
if((j+1<n)&&a[j+1]->val<a[j]->val)
{
j++;
}
if(a[j]->val>temp) break;

a[i]=a[j];
i=j;
j=2*i+1;
}

a[i]=ptemp;
}

void makeMinHeap(vector<ListNode*>& a)
{
int n=a.size();
for (int i = n/2-1; i >=0 ; --i)
{
minHeapfixdown(a,i,n);
}
}

};

注意:vector没有pop_front()方法,但是可以巧妙的 首尾交换,再pop_back()方法!!!!!神技
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 算法 leetcode