leetcode刷题笔记-23-合并K个升序链表
题目
https://leetcode.cn/problems/merge-k-sorted-lists/description/
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
1 2 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。
1 2 3
| 10 - 23 5 - 6 2 - 3 - 7
|
所以我们需要用小堆来维护最终的大小关系,首先是遍历给出的链表数组,将所有链表的头节点插入小堆,随后取出堆顶元素,链入最终链表,如果这个节点还有下一个节点,那么就将下一个节点也插入小堆。
这样才能保证最终的顺序性。
代码
注意,使用小堆需要用STD提供的priority_queue
容器,并自己写一个仿函数来比较两个链表节点的大小。
1 2 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.合并两个有序链表的练习。每次都选中两个链表进行合并,直到最终合并所有链表。
这里可以采用分治的思路,将链表数组拆分后进行合并。
代码
1 2 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()); } };
|