题目链接:23. 合并 K 个升序链表 - 力扣(LeetCode)
思路:
前有合并两个有序链表,感觉比较简单,没有认为合并K个升序链表难,其实直观上算法都是比较简单:首先对比每一个链表头部元素,找出最小的,放在目标链表中,更新这个链表头,直到遍历所有链表。主要是一些细节处理上。
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0) return nullptr;
//依旧是双指针,一个用来滑动更新,另一个用来记录返回的头
ListNode* head = new ListNode(-1);
ListNode* res = head;
while(lists.size() != 0)
{
//对于只有一个链表的,直接返回
if(lists.size() == 1)
{
head->next = lists[0];
break;
}
int min = __INT_MAX__;
int idx = 0;
//从第一个开始遍历
for(int i = 0; i < lists.size(); i++)
{
//这里挺重要
//如果某个元素已经为空链表,删除这个链表
//然后从i需要更新为i-1,否则continue后会i++,跳过一个元素
if(lists[i] == nullptr)
{
auto iter = lists.begin();
lists.erase(i + iter);
i = i-1;//重要!!!
continue;
}
//找到最小的链表头,及链表在vector中的idx
if(min > lists[i]->val)
{
min = lists[i]->val;
idx = i;
}
}
//此时检测list.size(),因为最后一个链表为空后
//上述会删除链表导致lists[]也为空
if(lists.size() == 0) break;
//head->next指向此次寻找到的最小头
head->next = lists[idx];
//head更新
head = head->next;
// lists[idx]位置的链表头更新
lists[idx] = lists[idx]->next;
if(head->next) head->next = nullptr;//断掉加入head的节点与原链表的关系
}
return res->next;
}
最近又重写了一遍,相当于把代码重构了一把,去掉不必要的
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0) return nullptr;
ListNode* Head = new ListNode();
ListNode* res = Head;
while(lists.size() != 0)
{
int min = __INT_MAX__;
int idx = 0;
for(int i = 0; i < lists.size(); i++)
{
if(lists[i] == nullptr)
{
lists.erase(i+lists.begin());
//这里需要注意,删除一个list之后,lists的size()已经改变,需要改变当前的索引i
i--;
continue;
}
if(min > lists[i]->val)
{
min = lists[i]->val;
idx = i;
}
}
//每次结束需要判断lists是否已经删空,如果空了,就要break出while
if(lists[idx] == nullptr) break;
Head->next = lists[idx];
Head = Head->next;
lists[idx] = lists[idx]->next;
}
return res->next;
}