合并k个已排序的链表_牛客题霸_牛客网【牛客题霸】收集各企业高频校招笔面试题目,配有官方题解,在线进行百度阿里腾讯网易等互联网名企笔试面试模拟考试练习,和牛人一起讨论经典试题,全面提升你的技术能力https://www.nowcoder.com/practice/65cfde9e5b9b4cf2b6bafa5f3ef33fa6
描述
合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。
- step 1:不管是Java还是C++都需要重载比较方法,构造一个比较链表节点大小的小顶堆。(Python版本直接加入节点值)
- step 2:先遍历k个链表头,将不是空节点的节点加入优先队列。
- step 3:每次依次弹出优先队列中的最小元素,将其连接在合并后的链表后面,然后将这个节点在原本链表中的后一个节点(如果不为空的话)加入队列,类似上述归并排序双指针的过程。
这里需要注意优先级队列的比较方式的书写 它的本质就是堆,那个比较方式是一个类,需要传入的参数是一个类型,如果使用模板的话就传入Com<T>,这个T就是存放元素的类型
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Com
{
public:
bool operator()(ListNode* left, ListNode* right)
{
return left->val > right->val;
}
};
class Solution {
public:
ListNode *mergeKLists(vector<ListNode*> &lists) {
if(lists.empty())return nullptr;
priority_queue<ListNode*, vector<ListNode*>, Com> q; // 创建一个优先级队列,按照大于的比较方式存储
for(auto &e : lists)
{
if(e!=nullptr) // 对每个不空的结点进行入队列
q.push(e);
}
ListNode* newhead = new ListNode(0);
newhead->next = nullptr;
ListNode* pre = newhead;
while(!q.empty())
{
ListNode* cur = q.top(); // cur标记当前堆顶结点
q.pop();
pre->next = cur; // 将它插入返回链表中
cur = cur->next; // 当前结点后移一步
if(cur)
q.push(cur); // 如果不为空就重新入队列
pre = pre->next;
}
return newhead->next;
}
};
数据范围:节点总数 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}