leetcode刷题笔记-23-合并K个升序链表
题目
https://leetcode.cn/problems/merge-k-sorted-lists/description/
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | 示例 1:输入: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
 
 示例 2:
 输入:lists = []
 输出:[]
 
 示例 3:
 输入:lists = [[]]
 输出:[]
 
 | 
最简单的思路就是用一个数组记录所有链表,再用sort将这个数组重排序,最后连成一个完整的升序链表。
思路1
思路1是用小堆来处理。
因为给出的链表已经是升序的,所以最终的有序链表的头节点,一定是给定的链表中的其中一个的头节点。
那么第二个节点呢?可能是另外一个链表的头节点,也有可能是当前选中的这个链表的第二个节点。比如下面的例子,第一个节点是2,第二个节点并不是其他链表的头节点,而是这一个链表的第二个节点3。
| 12
 3
 
 | 10 - 235 - 6
 2 - 3 - 7
 
 | 
所以我们需要用小堆来维护最终的大小关系,首先是遍历给出的链表数组,将所有链表的头节点插入小堆,随后取出堆顶元素,链入最终链表,如果这个节点还有下一个节点,那么就将下一个节点也插入小堆。
这样才能保证最终的顺序性。
代码
注意,使用小堆需要用STD提供的priority_queue容器,并自己写一个仿函数来比较两个链表节点的大小。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 
 | 
 
 
 
 
 
 
 
 
 class Solution {
 
 class MyCmp {
 public:
 bool operator()(ListNode* l, ListNode* r) {
 return l->val > r->val;
 }
 };
 
 public:
 ListNode* mergeKLists(vector<ListNode*>& lists) {
 
 priority_queue<ListNode*, vector<ListNode*>, MyCmp> que;
 
 
 for (auto& i : lists) {
 if (i != nullptr) {
 que.push(i);
 }
 }
 
 ListNode* phead = new ListNode;
 ListNode* cur = phead;
 while (!que.empty()) {
 
 ListNode* head = que.top();
 que.pop();
 
 if (head->next != nullptr) {
 que.push(head->next);
 }
 
 cur->next = head;
 cur = cur->next;
 }
 return phead->next;
 }
 };
 
 | 

思路2
方法2就是用之前写过的21.合并两个有序链表的练习。每次都选中两个链表进行合并,直到最终合并所有链表。
这里可以采用分治的思路,将链表数组拆分后进行合并。
代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 
 | class Solution {ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
 ListNode* head = new ListNode;
 ListNode* oldHead = head;
 ListNode *cur1 = list1, *cur2 = list2;
 while (cur1 != nullptr && cur2 != nullptr) {
 if (cur1->val >= cur2->val) {
 head->next = cur2;
 head = head->next;
 cur2 = cur2->next;
 } else {
 head->next = cur1;
 head = head->next;
 cur1 = cur1->next;
 }
 }
 
 if (cur1 == nullptr) {
 head->next = cur2;
 } else {
 head->next = cur1;
 }
 return oldHead->next;
 }
 
 ListNode* mergeKLists(vector<ListNode*>& lists, int i, int j) {
 int m = j - i;
 if (m == 0) {
 return nullptr;
 }
 if (m == 1) {
 return lists[i];
 }
 auto left = mergeKLists(lists, i, i + m / 2);
 auto right = mergeKLists(lists, i + m / 2, j);
 return mergeTwoLists(left, right);
 }
 
 public:
 ListNode* mergeKLists(vector<ListNode*>& lists) {
 return mergeKLists(lists, 0, lists.size());
 }
 };
 
 |