leetcode:23. 合并K个升序链表
题目
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例:
输入:lists = [[1,4,5],[1,3,4],[2,6]]输出:[1,1,2,3,4,4,5,6]解释:链表数组如下:[1->4->5,1->3->4,2->6]将它们合并到一个有序链表中得到。1->1->2->3->4->4->5->6
输入:lists = []输出:[]
输入:lists = [[]]输出:[]
解答 & 代码
解法一:小根堆(优先队列实现)
每次合并,都应该选择当前各个链表剩余部分最前面的节点的值的大小,选择值最小的节点插入。
问题就在于如何得到值最小的节点?可以用小根堆来存储各个链表剩余部分最前面的节点。
优先队列
priority_queue:
- 头文件:
#include <queue>- 定义:
priority_queue<Type, Container, Functional>
- 大根堆:
priority_queue<int> maxHeaporpriority_queue<int, vector<int>, less<int>> maxHeap- 小根堆:
priority_queue<int, vector<int>, greater<int>> minHeap- 自定义类型:如下面代码所示
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/class Solution {private:// 小根堆的回调函数struct cmp {bool operator() (ListNode* node1, ListNode* node2) {return node1->val > node2->val;}};public:ListNode* mergeKLists(vector<ListNode*>& lists) {// 小根堆(基于优先队列)priority_queue<ListNode*, vector<ListNode*>, cmp> minHeap;// 初始将每个链表的头节点(如果不为空)存入小根堆for(int i = 0; i < lists.size(); ++i){if(lists[i] != nullptr)minHeap.push(lists[i]);}ListNode* dummyHead = new ListNode();ListNode* pre = dummyHead;while(!minHeap.empty()){ListNode* minNode = minHeap.top();minHeap.pop();pre->next = minNode;pre = pre->next;if(minNode->next != nullptr)minHeap.push(minNode->next);}return dummyHead->next;}};
复杂度分析:设一共 K 个链表,这 K 个链表节点总数为 N
- 时间复杂度 O(N × logK):优先队列中元素不超过 K 个,因此插入和删除时间代价为 O(logK),N 个节点都会插入优先队列并删除一次
- 空间复杂度 O(K):优先队列中的元素不超过 K 个
执行结果:
执行结果:通过执行用时:20 ms, 在所有 C++ 提交中击败了 79.35% 的用户内存消耗:12.9 MB, 在所有 C++ 提交中击败了 74.70% 的用户
