问题描述
合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。
数据范围:节点总数 0≤n≤50000≤n≤5000,每个节点的val满足 ∣val∣<=1000∣val∣<=1000
要求:时间复杂度 O(nlogn)O(nlogn)
示例1
输入:
[{1,2,3},{4,5,6,7}]
返回值:
{1,2,3,4,5,6,7}
示例2
输入:
[{1,2},{1,4,5},{6}]
返回值:
{1,1,2,4,5,6}
解题思路
逐步找到所有链表头节点中值最小的节点,将其加入结果链表,同时将对应链表的头节点向后移动,直到所有链表都为空。
合并过程演示
代码实现
ListNode* mergeKLists(vector<ListNode*>& lists) {
// write code here
ListNode* rhead = nullptr;
ListNode* rtail = nullptr;
while (true)
{
int minIndex = -1;
int i = lists.size();
while (i--)
{
if (lists[i] != nullptr )
{
if (minIndex == -1)
{
minIndex = i;
}
else if (lists[i]->val < lists[minIndex]->val)
{
minIndex = i;
}
}
}
if (minIndex == -1)
{
return rhead;
}
if (rhead == nullptr)
{
rhead = rtail = lists[minIndex];
}
else
{
rtail->next = lists[minIndex];
rtail = rtail->next;
}
lists[minIndex] = lists[minIndex]->next;
}
}
代码解析
1. 初始化合并链表头指针和尾指针
使用 rhead
保存最终合并链表的头节点,用于返回结果。
使用 rtail
辅助插入新节点。
ListNode* rhead = nullptr;
ListNode* rtail = nullptr;
2. 遍历链表数组,查找当前最小节点
使用 minIndex
记录值最小节点所在链表的索引。
遍历所有链表头节点,比较值大小更新 minIndex
。
int minIndex = -1;
int i = lists.size();
while (i--)
{
if (lists[i] != nullptr)
{
if (minIndex == -1 || lists[i]->val < lists[minIndex]->val)
{
minIndex = i;
}
}
}
3. 判断退出条件
当所有链表都遍历完成(即 minIndex == -1
),返回结果链表头节点。
if (minIndex == -1)
{
return rhead;
}
4. 更新合并链表
若合并链表为空(第一次插入节点),将最小值节点作为头节点。
否则,追加最小值节点到尾部。
if (rhead == nullptr)
{
rhead = rtail = lists[minIndex];
}
else
{
rtail->next = lists[minIndex];
rtail = rtail->next;
}
5. 移动链表头节点
将已插入节点的链表头指针向后移动,继续下一次循环。
lists[minIndex] = lists[minIndex]->next;
总结
本文实现了逐步查找最小值的 mergeKLists
方法,逻辑直观且易于实现,但在 kkk 较大时效率较低。实际应用中,结合优先队列或分治法可以显著优化性能。读者可以根据具体需求选择合适的实现方式。