题目
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
算法实现:方法一,两两合并
/**
* 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 length = lists.size();
if (length == 0) {
return nullptr;
}
else if (length == 1) {
return lists[0];
}
ListNode* p = lists[0];
for (int i = 1; i < length; i++) {
p = merge2(p, lists[i]);
}
return p;
}
ListNode* merge2(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(0);
ListNode* p = head;
while (l1 && l2) {
if (l1->val < l2->val) {
p->next = l1;
l1 = l1->next;
}
else {
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
while (l1) {
p->next = l1;
l1 = l1->next;
p = p->next;
}
while (l2) {
p->next = l2;
l2 = l2->next;
p = p->next;
}
return head->next;
}
};
结果
可以看到,这种方法是比较慢的
改进:如果一个链表为空,直接将另一个链在链表尾部
/**
* 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 length = lists.size();
if (length == 0) {
return nullptr;
}
else if (length == 1) {
return lists[0];
}
ListNode* p = lists[0];
for (int i = 1; i < length; i++) {
p = merge2(p, lists[i]);
}
return p;
}
ListNode* merge2(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(0);
ListNode* p = head;
while (l1 && l2) {
if (l1->val < l2->val) {
p->next = l1;
l1 = l1->next;
}
else {
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
p->next = l1 ? l1 : l2;
return head->next;
}
};
可以看到快了很多
方法二:双端队列
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int length = lists.size();
if (length == 0) {
return nullptr;
}
else if (length == 1) {
return lists[0];
}
queue<ListNode*> waiting(deque<ListNode*>(lists.begin(), lists.end()));
while (waiting.size() > 1) {
ListNode* l1 = waiting.front();
waiting.pop();
ListNode* l2 = waiting.front();
waiting.pop();
waiting.push(merge2(l1, l2));
}
return waiting.front();
}
ListNode* merge2(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(0);
ListNode* p = head;
while (l1 && l2) {
if (l1->val < l2->val) {
p->next = l1;
l1 = l1->next;
}
else {
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
p->next = l1 ? l1 : l2;
return head->next;
}
};