方法一:归并排序
利用双指针和分治(递归)的思想来求解
可以将问题分解为两个有序链表的合并的小问题,并且不断地向上递归,最终就可以将K个链表按顺序合并到一起。
时间复杂度:o(nlogk);递归有logk层,n为所有链表的总结点数,复杂度为o(nlogk)。
空间复杂度:o(logk),需要logk的递归栈。
class Solution {
public:
//合并两个有序链表
ListNode* merge(ListNode* phead1, ListNode* phead2) {
if (phead1 == nullptr)
return phead2;
if (phead2 == nullptr)
return phead1;
ListNode* res = new ListNode(0);
ListNode* cur = res;
while (phead1 && phead2) {
if (phead1->val < phead2->val) {
cur->next = phead1;
phead1 = phead1->next;
} else {
cur->next = phead2;
phead2 = phead2->next;
}
cur = cur->next;
}
if (phead1)
cur->next = phead1;
if (phead2)
cur->next = phead2;
return res->next;
}
ListNode* divideLists(vector<ListNode*>& lists, int left, int right) {
//特殊情况处理
if (left > right)
return nullptr;
if (left == right)
return lists[left];
int mid = (left + right) / 2;
//拆分为子问题,并且向上递归,最终的合并所有的链表
return merge(divideLists(lists, left, mid), divideLists(lists, mid + 1, right));
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
return divideLists(lists, 0, lists.size() - 1);
}
};
方法二:辅助空间排序
1、创建数组,将K个链表存储到数组中;
2、对数组中的元素进行排序(快排);
3、将数组转换为链表即得到按顺序合并后的链表。
时间复杂度:o(nlogn)。遍历需要的时间为o(n);快排需要的时间为o(nlogn)。
空间复杂度:o(n)。需要辅助数组存储所有链表的结点的值。
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if (lists.size() == 0)
return nullptr;
if (lists.size() == 1)
return lists[0];
vector<int> vect;
for (int i = 0; i < lists.size(); i++) {
ListNode* temp = lists[i];
while (temp) {
vect.push_back(temp->val);
temp = temp->next;
}
}
sort(vect.begin(), vect.end());
ListNode* res = new ListNode(0);
ListNode* phead = res;
for (int i = 0; i < vect.size(); i++) {
phead->next = new ListNode(vect[i]);
phead = phead->next;
}
phead->next = nullptr;
return res->next;
}
};
拓展思路
方法三:小顶堆

京公网安备 11010502036488号