Leetcode: 23.Merge k Sorted Lists
題目一目瞭然就是要對k個已經排序了的list進行合併排序,最後返回一個合併好的序列。
priority queue
將每個list的最小節點放入一個priority queue (min heap)中。之後每從queue中取出一個節點,則將該節點在其list中的下一個節點插入,以此類推直到全部節點都經過priority queue。由於priority queue的大小爲始終爲k,而每次插入的複雜度是log k
,一共插入過nk
個節點。時間複雜度爲O(nk logk)
,空間複雜度爲O(k)
。
注意C++的STL中的priority queue默認是max heap,需要定義一個新的比較函數。
class Solution {
public:
struct compNode {
bool operator()(ListNode *p, ListNode *q) const {
return p->val>q->val;
}
};
ListNode *mergeKLists(vector<ListNode *> &lists) {
priority_queue<ListNode*, vector<ListNode*>, compNode> pq;
ListNode *dummy = new ListNode(0), *tail = dummy;
for(int i=0; i<lists.size(); i++)
if(lists[i]) pq.push(lists[i]);
while(!pq.empty()) {
tail->next = pq.top();
tail = tail->next;
pq.pop();
if(tail->next) pq.push(tail->next);
}
return dummy->next;
}
};
Merge two lists
利用合併兩個list的方法,依次將每個list合併到結果的list中。這個方法的空間複雜度爲O(1),時間複雜度爲:
2n + 3n + ... + kn = [(k+1)*k/2-1]*n = O(nk^2)
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
ListNode *ret = NULL;
for(int i=0; i<lists.size(); i++)
ret = merge2Lists(ret, lists[i]);
return ret;
}
ListNode* merge2Lists(ListNode *h1, ListNode *h2) {
ListNode *dummy = new ListNode(0), *tail = dummy;
while(h1 && h2) {
if(h1->val<=h2->val) {
tail->next = h1;
h1 = h1->next;
}
else {
tail->next = h2;
h2 = h2->next;
}
tail = tail->next;
}
tail->next = h1 ? h1 : h2;
return dummy->next;
}
};
二分法
類似merge sort,每次將所有的list兩兩之間合併,直到所有list合併成一個。如果用迭代而非遞歸,則空間複雜度爲O(1)。時間複雜度:
2n * k/2 + 4n * k/4 + ... + (2^x)n * k/(2^x) = nk * x
k/(2^x) = 1 -> 2^x = k -> x = log2(k)
所以時間複雜度爲O(nk log(k))
,與方法一相同。
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
if(lists.empty()) return NULL;
int end = lists.size()-1;
while(end>0) {
int begin = 0;
while(begin<end) {
lists[begin] = merge2Lists(lists[begin], lists[end]);
begin++;
end--;
}
}
return lists[0];
}
ListNode* merge2Lists(ListNode *h1, ListNode *h2) {
ListNode *dummy = new ListNode(0), *tail = dummy;
while(h1 && h2) {
if(h1->val<=h2->val) {
tail->next = h1;
h1 = h1->next;
}
else {
tail->next = h2;
h2 = h2->next;
}
tail = tail->next;
}
tail->next = h1 ? h1 : h2;
return dummy->next;
}
};
粗暴法
直接把所有節點push進一個vector,然後sort一下,重新串起來就好了,時間複雜度爲O(nk log(nk)),也能過……就是這樣粗暴。