LeetCode | Merge k Sorted Lists(归并k个链表)
来源:互联网 发布:python bufferreader 编辑:程序博客网 时间:2024/04/29 11:37
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
将k个链表排序,并求出时间复杂度。
方案一:
第一个和第二个合并,结果在和第三个合并......最后和第k个合并。本来以为时间复杂度为nk,其实不然。前两个合并后,耗费2n个时间。再和第三个合并,耗费3n个时间,最后和第k个合并,耗费kn个时间。总的时间为(2+3...+k)*n = n*k*k的时间复杂度。所有不可取。这种好实现,循环n次,然后两个两个合并即可。
方案二:
其实可以把k个链表看成k个点,对一个含有k个元素的数组,我们有快速排序、归并排序、堆排序等。但由于这道题目的应用环境,每个元素含有n个数据,快速排序不可能实现。那么考虑归并排序。其实在方案一当中,两两之间的合并已经是归并排序了。那么现在对整个k个链表应用归并排序。每次归并排序,nk个元素都要比较,时间复杂度为nk,一共需要logk次归并,所以时间复杂度为O(nklogk)。
有两种实现方法,递归和循环。其中循环的方法值得借鉴
//通用方法,这里不管有多少个链表ListNode *MergeKLists(LinkList arr[],int l,int h){ if(l < r){ int m = (l+r)/2; return Merge(MergeKLists(arr,l,m),MergeKLists(arr,m+1,h)); } return arr[l];}//当能求得链表的个数的时候,可以利用循环代替递归来进行ListNode *MergeKLists(LinkList arr[],int k){ LinkList first,second,result; if(k < 1) return NULL; if(k == 1) return arr[0]; while(k > 1){ int half = (k+1)/2; //这里必须加1,因为k代表的是个数,当循环结束后,会有k = half,当k为基数的时候,个数会减少 for(int i = 0;i + half < size;i++){ first = arr[i]; second = arr[i+half]; result = Merge(first,second); arr[i] = result; } k = half; } return arr[0];}ListNode *Merge(LinkList l1,LinkList l2){ ListNode *dummy = (LinkList)malloc(sizeof(ListNode)); dummy->next = l1; //初始化,为后面求解方便 ListNode *cur = dummy; //父节点 while(l1 != NULL && l2 != NULL){ if(l1->data < l2->data) l1 = l1->next; else{ LinkList temp = l2->next; l2->next = cur->next; cur->next = l2; l2 = temp; } cur = cur->next; } if(l2 != NULL) cur->next = l2; return dummy->next;}假设总共有k个list,每个list的最大长度是n,那么运行时间满足递推式T(k) = 2T(k/2)+O(n*k)。根据主定理,可以算出算法的总复杂度是O(nklogk)。如果不了解主定理的朋友,可以参见 主定理-维基百科 。空间复杂度的话是递归栈的大小O(logk)。
方案三:
我们还要尝试堆排序。我们可以先将k个链表的第一个元素进行堆排序,那么取出最小数据,并将最小数据所在链表的下一个元素放入堆中。因此一次取元素,时间复杂度为logk,一共有nk个元素。总的时间复杂度为O(nklogk)。空间复杂度是堆的大小,即为O(k)。
由于以往看到的堆排序都是在一个数组中进行,比较好写,但是这个题目的元素是一个结点,并且也不在数组中。所以可能的堆排序结点为(没有具体实现,只是考虑了一下):
typedef struct Node{ int data; struct Node *next;}ListNode,*LinkList;typedef struct HeapNode{ ListNode *LNode; struct HeapNode *left,*right;}HeapNode;
但是在C++中好实现,已经封装好了堆的实现。代码如下:
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */class ListNodeCompare:public binary_function<ListNode*,ListNode*,bool>{public: bool operator()(ListNode* t1,ListNode* t2)const { if ( !t1||!t2 ) return !t2; return t1->val>t2->val; }};class Solution {public: ListNode *mergeKLists(vector<ListNode *> &lists) { // Note: The Solution object is instantiated only once and is reused by each test case. if (lists.empty()) return NULL; priority_queue<ListNode*,vector<ListNode*>,ListNodeCompare> Q; for(int i=0;i<lists.size();i++) if ( lists[i]!=NULL) Q.push(lists[i]); ListNode guard(-1); ListNode* tail=&guard; while(!Q.empty()) { ListNode* toAdd=Q.top(); Q.pop(); tail->next=toAdd; tail=tail->next; if (toAdd->next) Q.push(toAdd->next); } return guard.next; }};
推荐链接:PriorityQueue
- LeetCode | Merge k Sorted Lists(归并k个链表)
- Merge k Sorted Lists 归并K个链表
- Merge k Sorted Lists 归并k个链表
- LeetCode Merge k Sorted Lists 归并
- 【leetcode】Merge k Sorted Lists (归并排序)
- LeetCode 23 Merge k Sorted Lists(归并)
- LeetCode(23)Merge k Sorted Lists
- LeetCode: Merge k Sorted Lists
- LeetCode Merge k Sorted Lists
- LeetCode: Merge k Sorted Lists
- [Leetcode] Merge k Sorted Lists
- [Leetcode] Merge k Sorted Lists
- [Leetcode] Merge K sorted lists
- [LeetCode]Merge k Sorted Lists
- [LeetCode] Merge k Sorted Lists
- LeetCode-Merge k Sorted Lists
- LeetCode: Merge k Sorted Lists
- LeetCode - Merge k Sorted Lists
- 并查集(Union-Find)算法介绍
- Deep Learning:Overview and Trend (Andrew Ng学术报告)
- UVA10106 Product
- Oracle 11g ASM 特性
- spring-batch
- LeetCode | Merge k Sorted Lists(归并k个链表)
- 一个子串在整串中出现的次数
- wiki 1052 地鼠游戏
- MFC 读取EXCEL中数据
- C与指针——与谭浩强不同的C
- HDU 2072 - 单词数 (Trie)
- hdu4847 Wow! Such Doge!(简单题+坑爹的输入)
- Peter Kovesi MATLAB and Octave Functions for Computer Vision and Image Processing
- 对抗脂肪君经拿滚系列之二 - 减脂最大杀手 基代损伤