题目
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6]
输出: 1->1->2->3->4->4->5->6
(题目出处 https://leetcode-cn.com/problems/merge-k-sorted-lists/)
题目分析
首先我们需要K的指针指向每个链表的最前端,每次选出一个最小的和次小的结点进行连接。那么本题的要点就是快速地从K的指针中选出一个最小的和次小的指针。直接扫描一遍肯定是浪费时间的。我们可以用最小堆来实现,把k个指针插入到堆中,我们一个每次以O(lgn)的时间选出一个最小的元素,选出两个指针后,把最小的指针的下一个节点插入到堆中,插入时间也是O(lgn)。如此进行下去当堆为空的时候我们的链表也就合并完了。
/*
C++代码
*/
struct ListNodeCompare {
bool operator()(ListNode* a, ListNode* b) {
if (a == NULL && b != NULL) {
return false;
}
if (a != NULL && b == NULL) {
return true;
}
return a->val > b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.empty()) {
return NULL;
}
//优先队列
priority_queue <ListNode*, vector<ListNode*>, ListNodeCompare> queue;
for (auto p : lists) {
if (p != NULL) {
queue.push(p);
}
}
if (queue.empty()) {
return NULL;
}
ListNode* p = NULL;
ListNode* q = NULL;
ListNode* head = NULL;
head = queue.top();
queue.pop();
if (head->next != NULL) {
queue.push(head->next);
}
p = head;
while (!queue.empty()) {
q = queue.top();
queue.pop();
if (q->next != NULL) {
queue.push(q->next);
}
p->next = q;
p = p->next;
}
return head;
}
值得注意的是结构体“ListNodeCompare”作为一个参数传递给了优先队列,这个结构体重载了“()”运算符,我们称之为函数对象,或者行为像函数的对象,使用时直接“ListNodeCompare(参数列表)”即可使用。作为优先队列的参数传递是因为优先队列中需要一个标准去判断大小。
时间复杂度O(n) 空间复杂度O(k)