題目:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. Example: | 合并 k 個排序連結清單,傳回合并後的排序連結清單。請分析和描述算法的複雜度。 示例: |
思路:
(1)可以借鑒合并兩個有序連結清單的思路,比如1,2,3,4,5連結清單,可以1,2合并,然後将結果與3合并。這樣很慢。我們 可以對其二分,再兩兩合并,然後再結合。比如1,2,3,4,5連結清單,我們分别合并(1,2)(3,4)(5)或者我們底下程式采用的這種(1,4)(2,5)(3),這就類似于歸并排序,采用分治法。這樣快很多。 底下的程式k=(n+1)/2表示合并之後總共有幾個表,比如1,2,3,4,5合并一次後有3個表。
/**
* 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) {
int n=lists.size(),k;
if(n==0) return NULL;
while(n>1)
{
k = (n+1)/2;
for(int i=0;i<n/2;++i)
lists[i] = mergelist(lists[i],lists[i+k]);
n=k;
}
return lists[0];
}
ListNode* mergelist(ListNode* l1,ListNode *l2)//合并倆連結清單
{
ListNode* head=new ListNode(-1);
ListNode* cur = head;
while(l1 && l2)
{
if(l1->val < l2->val)
{
cur->next=l1;
l1=l1->next;
}else{
cur->next = l2;
l2 = l2->next;
}cur = cur->next;
}
if(l1) cur->next = l1; //記得不要忘了還要連接配接另外一個連結清單
if(l2) cur->next = l2;
return head->next;
}
};
(2)用最小堆,首先把k個連結清單的首元素都加入最小堆中,它們會自動排好序。然後我們每次取出最小的那個元素加入我們最終結果的連結清單中,然後把取出元素的下一個元素再加入堆中,下次仍從堆中取出最小的元素做相同的操作,以此類推,直到堆中沒有元素了,此時k個連結清單也合并為了一個連結清單,傳回首節點即可
struct cmp {
bool operator () (ListNode *a, ListNode *b) {
return a->val > b->val;
}
};
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
priority_queue<ListNode*, vector<ListNode*>, cmp> q;
for (int i = 0; i < lists.size(); ++i) {
if (lists[i]) q.push(lists[i]);
}
ListNode *head = NULL, *pre = NULL, *tmp = NULL;
while (!q.empty()) {
tmp = q.top();
q.pop();
if (!pre) head = tmp;
else pre->next = tmp;
pre = tmp;
if (tmp->next) q.push(tmp->next);
}
return head;
}
};
參考:http://www.cnblogs.com/grandyang/p/4606710.html