1. 题目
合并k条升序链表
2. 分析
将 Merge Two Sorted Lists 从2个扩展到k个
1:最直接的思路就是两两合并,1,2先合并,合并好了再跟3/…/k合并
注意
- ListNode *p = lists[0];而非ListNode *p = &lists[0];
- i的下标从1开始
- p = mergeTwoLists(p, lists[i]);函数调用结果要赋给p返回
2:借助归并排序的思路,采用分治法Divide and Conquer Approach
先分成两个子任务,然后递归求子任务,最后回溯回来
简单来说就是不停的对半划分,比如k个链表先划分为合并两个k/2个链表的任务, 再不停的往下划分,直到划分成只有1或2个链表的任务,开始合并
注意
- left, right的大小要分3种情况讨论
- mergeLists(lists, mid + 1, right);而非mergeLists(lists, mid, right);不要写错
3:借助数据结构—最小堆
先把k个链表的首元素都放入最小堆中自动排好序
每次取出最小节点插入结果链表
将取出节点的下一节点再放入堆中
重复这个过程,直到最小堆为空
则合并成功,返回首节点即可
注意
- push进q之前应该判断lists[i] != nullptr
- tmp = q.top();而非tmp = q.front();
- if(tmp->next)之后是q.push(tmp->next);而非q.push(tmp);
3. 代码
函数 mergeTwoLists 在Merge Two Sorted Lists中任选一种复用均可
1)
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int len = lists.size();
if(len == 0)
return NULL;
ListNode *cur = lists[0];
for(int i = 1; i < len; ++i)
{
cur = mergeTwoLists(cur, lists[i]);
}
return cur;
}
ListNode* mergeTwoLists(ListNode *l1, ListNode *l2) {
// 复用mergeTwoLists
}
};
2)
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int len = lists.size();
if(len == 0)
return NULL;
return mergeKListsRecursive(lists, 0, len - 1);
}
ListNode* mergeKListsRecursive(vector<ListNode*>& lists, int left, int right)
{
if(left == right)
return lists[left];
else if(left < right)
{
int mid = left + (right - left) / 2;
ListNode *l = mergeKListsRecursive(lists, left, mid);
ListNode *r = mergeKListsRecursive(lists, mid + 1, right);
return mergeTwoLists(l, r);
}
else
return NULL;
}
ListNode* mergeTwoLists(ListNode *l1, ListNode *l2) {
// 复用mergeTwoLists
}
};
3)
// 不要遗漏 operator 后面的 () 以及 struct 最后的;
struct cmp
{
bool operator()(ListNode *a, ListNode *b)
{
return a->val > b->val;
}
};
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int len = lists.size();
if(len <= 0)
return NULL;
priority_queue<ListNode*, vector<ListNode*>, cmp> q;
// 注意一定要判断 lists[i] != NULL
// 否则后面会出错的
for(int i = 0; i < len; ++i)
{
if(lists[i] != NULL)
{
q.push(lists[i]);
}
}
ListNode *head = NULL;
ListNode *prev = NULL;
ListNode *temp = NULL;
while(!q.empty())
{
temp = q.top();
q.pop();
if(prev == NULL)
head = temp;
else
prev->next = temp;
// prev可能为 NULL 所以不能写 prev = prev->next;
prev = temp;
// push前一定要判断 lists[i] != NULL
if(temp->next != NULL)
q.push(temp->next);
}
return head;
}
};