题目描述
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
解题思路:借鉴于合并两个排序链表的题,采用分治法来解决该问题
不停的对半划分,比如k个链表先划分为合并两个k/2个链表的任务,再不停的往下划分,直到划分成只有一个或两个链表的任务,开始合并。举个例子来说比如合并6个链表,那么按照分治法,我们首先分别合并1和4,2和5,3和6。这样下一次只需合并3个链表,我们再合并1和3,最后和2合并就可以了。
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 int n = lists.size(); 13 if(n == 0) 14 return NULL; 15 16 while(n > 1) 17 { 18 int k = (n+1)/2; 19 for(int i=0;i<n/2;i++) 20 { 21 lists[i] = merge2Lists(lists[i],lists[i+k]); 22 } 23 n = k; 24 } 25 return lists[0]; 26 } 27 ListNode *merge2Lists(ListNode *l1, ListNode *l2) 28 { 29 ListNode *head = new ListNode(-1); 30 ListNode *cur = head; 31 while (l1 && l2) 32 { 33 if (l1->val < l2->val) 34 { 35 cur->next = l1; 36 l1 = l1->next; 37 } 38 else 39 { 40 cur->next = l2; 41 l2 = l2->next; 42 } 43 cur = cur->next; 44 } 45 if (l1) cur->next = l1; 46 if (l2) cur->next = l2; 47 return head->next; 48 } 49 };
方法二:利用了最小堆这种数据结构,我们首先把k个链表的首元素都加入最小堆中,它们会自动排好序。然后我们每次取出最小的那个元素加入我们最终结果的链表中,然后把取出元素的下一个元素再加入堆中,下次仍从堆中取出最小的元素做相同的操作,以此类推,直到堆中没有元素了,此时k个链表也合并为了一个链表,返回首节点即可,代码如下:
1 struct cmp { 2 bool operator () (ListNode *a, ListNode *b) { 3 return a->val > b->val; 4 } 5 }; 6 7 class Solution { 8 public: 9 ListNode *mergeKLists(vector<ListNode *> &lists) { 10 priority_queue<ListNode*, vector<ListNode*>, cmp> q; 11 for (int i = 0; i < lists.size(); ++i) { 12 if (lists[i]) q.push(lists[i]); 13 } 14 ListNode *head = NULL, *pre = NULL, *tmp = NULL; 15 while (!q.empty()) { 16 tmp = q.top(); 17 q.pop(); 18 if (!pre) head = tmp; 19 else pre->next = tmp; 20 pre = tmp; 21 if (tmp->next) q.push(tmp->next); 22 } 23 return head; 24 } 25 };