0
点赞
收藏
分享

微信扫一扫

[链表]BM5 合并k个已排序的链表-较难

​​BM5 合并k个已排序的链表​​

描述

合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。数据范围:节点总数满足 [链表]BM5 合并k个已排序的链表-较难_链表,链表个数满足 [链表]BM5 合并k个已排序的链表-较难_set_02 ,每个链表的长度满足 [链表]BM5 合并k个已排序的链表-较难_set_03 ,每个节点的值满足 [链表]BM5 合并k个已排序的链表-较难_合并K个已序链表_04要求:时间复杂度 [链表]BM5 合并k个已排序的链表-较难_set_05

示例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}

题解

方法一:参考合并2个链表的方式进行k个链表合并

#include <bits/stdc++.h>

struct ListNode
{
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(nullptr)
{
}
ListNode() = default;
};

ListNode *merge_list(ListNode *left, ListNode *right)
{
if (left == nullptr)
{
return right;
}

if (right == nullptr)
{
return left;
}

if (left->val > right->val)
{
return merge_list(right, left);
}

auto head = left;
auto tail_node = head;
left = left->next;
while (left != nullptr || right != nullptr)
{
if (left == nullptr)
{
auto next = right->next;
tail_node->next = right;
tail_node = tail_node->next;
right = next;
continue;
}
if (right == nullptr)
{
auto next = left->next;
tail_node->next = left;
tail_node = tail_node->next;
left = next;
continue;
}

if (left->val < right->val)
{
auto next = left->next;
tail_node->next = left;
tail_node = tail_node->next;
left = next;
}
else
{
auto next = right->next;
tail_node->next = right;
tail_node = tail_node->next;
right = next;
}
}
return head;
}


class Solution
{
public:
// 时间复杂度超出题目规定
static ListNode *mergeKLists(std::vector<ListNode *> &lists)
{
if (lists.size() == 0)
{
return nullptr;
}

if (lists.size() == 1)
{
return lists[0];
}

auto head = lists[0];
for (int i = 1; i < lists.size(); ++i)
{
auto right = lists[i];
head = merge_list(head, right);
}
return head;
}
};

ListNode *create_list(const std::vector<int> &v)
{
ListNode head;
ListNode *phead = &head;
for (auto &data : v)
{
auto node = new ListNode;
node->val = data;
node->next = nullptr;
phead->next = node;
phead = phead->next;
}
return head.next;
}

std::vector<ListNode *> create_list_n(const std::vector<std::vector<int>> &v)
{
std::vector<ListNode *> lists;
for (int i = 0; i < v.size(); ++i)
{
lists.push_back(create_list(v[i]));
}

return lists;
}

int main()
{
std::vector<ListNode *> lists = create_list_n(std::vector<std::vector<int>>{{-3, -3, -3}, {-9, -8, -7, -7, -6, -4, 2}, {-2, 3}, {-8, -4, -3, -2}});
auto head = Solution::mergeKLists(lists);
while (head != nullptr)
{
std::cout << head->val << " ";
head = head->next;
}
std::cout << std::endl;
return 0;
}

代码实现很简单,但是存在时间复杂度不满足题目要求的问题。


方法二:借助于set的实现

// 比较仿函数
class cmp
{
public:
bool operator()(const ListNode *left, const ListNode *right)
{
return left->val < right->val;
}
};

class Solution
{
public:
ListNode *mergeKLists(std::vector<ListNode *> &lists)
{
if (lists.size() == 0)
{
return nullptr;
}

if (lists.size() == 1)
{
return lists[0];
}

// 这里要使用multiset,如果使用set,那么会导致val相同的节点被跳过!!
std::multiset<ListNode *, cmp> s;
for (int i = 0; i < lists.size(); ++i)
{
if (lists[i] != nullptr)
{
s.insert(lists[i]);
}
}

ListNode *head = nullptr;
ListNode *tail_node = nullptr;
while (!s.empty())
{
if (head == nullptr)
{
head = *s.begin();
tail_node = head;
s.erase(s.begin());
if (tail_node->next != nullptr)
{
s.insert(tail_node->next);
}
continue;
}

auto cur_node = *s.begin();
auto next = cur_node->next;
tail_node->next = cur_node;
tail_node = tail_node->next;
s.erase(s.begin());
if (next != nullptr)
{
s.insert(next);
}
}

return head;
}
};

上面的代码很简短,关键点就是使用set自动排序,让其第一个元素永远存放最小的链表元素,每次取出begin,然后将begin的next节点再次插入set中,直到set为空跳出循环。


举报

相关推荐

0 条评论