题目描述:
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [ 1->4->5, 1->3->4, 2->6 ] 将它们合并到一个有序链表中得到。 1->1->2->3->4->4->5->6
示例 2:
输入:lists = [] 输出:[]
示例 3:
输入:lists = [[]] 输出:[]
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i]
按 升序 排列lists[i].length
的总和不超过10^4
题目链接:
解题主要思想:
刚开始我是借助优先级队列,建小根堆完成此题目,编写简单。之后在网上了解到还有一种以分治归并思想的解法,即将两个相邻的链表合并,再往上合并。
解题代码:
(借助优先级队列建小根堆)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
auto cmp = [](const ListNode* l1, const ListNode* l2){return l1->val > l2->val;};
// 建小根堆
priority_queue<ListNode*, vector<ListNode*>, decltype(cmp)> heap(cmp);
// 将每个头节点push到堆中
for (auto& l : lists) {
if (l) heap.push(l);
}
// 构造目标链表
ListNode head(0);
ListNode* prev = &head;
while (!heap.empty()) {
ListNode* cur = heap.top();
heap.pop();
prev->next = cur;
prev = prev->next;
if (cur->next) heap.push(cur->next);
}
return head.next;
}
};
(分治归并)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
return merge(lists, 0, lists.size()-1);
}
ListNode* merge(vector<ListNode*>& lists, int left, int right)
{
if (left > right) return nullptr;
if (left == right) return lists[left];
int mid = (left+right) >> 1;
ListNode* l1 = merge(lists, left, mid);
ListNode* l2 = merge(lists, mid+1, right);
// 合并两个链表
return _merge(l1, l2);
}
ListNode* _merge(ListNode* l1, ListNode* l2)
{
if (l1 == nullptr) return l2;
if (l2 == nullptr) return l1;
ListNode head(0);
ListNode* cur1 = l1, *cur2 = l2, *prev = &head;
// 升序合并两个链表
while (cur1 && cur2) {
if (cur1->val < cur2->val) {
prev->next = cur1;
prev = prev->next;
cur1 = cur1->next;
}
else {
prev->next = cur2;
prev = prev->next;
cur2 = cur2->next;
}
}
while (cur1) {
prev->next = cur1;
prev = prev->next;
cur1 = cur1->next;
}
while (cur2) {
prev->next = cur2;
prev = prev->next;
cur2 = cur2->next;
}
return head.next;
}
};