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)),也能过……就是这样粗暴。