【困难】23-合并K个排序链表 Merge k Sorted Lists
题目
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
解法
方法一:逐一合并
解题思路
在21题(【简单】21-合并两个有序链表 Merge Two Sorted Lists)已经做过了两个有序链表的合并,所以每次将两个链表合并成一个新的链表,然后再把下一个链表与这个链表合并。
代码
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1 == NULL) return l2;
if(l2 == NULL) return l1;
ListNode head(0);
ListNode *curr = &head;
while(l1 != NULL || l2 != NULL){
if(l1 == NULL) {curr->next = l2; return head.next;}
if(l2 == NULL) {curr->next = l1; return head.next;}
if(l1->val < l2->val){
curr->next = l1;
curr = curr->next;
l1 = l1->next;
}
else{
curr->next = l2;
curr = curr->next;
l2 = l2->next;
}
}
return head.next;
}
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0) return NULL;
ListNode *res = lists[0];
for (int i = 1; i < lists.size(); ++i) {
res = mergeTwoLists(res, lists[i]);
}
return res;
}
};
方法二:分治与归并
解题思路
方法一是逐一将链表与已知的链表融合在一起,自然想到,我们可以每两个链表合并在一起,得到n/2个链表,然后重复过程,得到n/4个链表,一直到得到最后的链表,这是归并的思路,那么反过来就是,把一组链表分成两半,这最终的结果就是对这两半各自得到的链表的求合并结果,也就是分治的思想,分支代码在下面。
代码
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0) return NULL;
return distribute(lists, 0, lists.size()-1);
}
ListNode* distribute(vector<ListNode*> lists, int left, int right){
if(left < right){
int mid = (left+right) / 2;
return mergeTwo(distribute(lists, left, mid), distribute(lists, mid+1, right));
}
return lists[left];
}
ListNode* mergeTwo(ListNode* left, ListNode* right){
ListNode* res = new ListNode(0);
ListNode* curr = res;
while(left != NULL && right != NULL){
bool nextIsLeft = left->val < right->val;
curr->next = nextIsLeft ? left : right;
left = nextIsLeft ? left->next : left;
right = nextIsLeft ? right : right->next;
curr = curr->next;
}
curr->next = left == NULL ? right : left;
return res->next;
}
};
方法三:优先队列
解题思路
优先队列会把更大优先级的元素排在前面,所以可以把链表中的元素作为优先级的值放入优先队列,也就是写一个比较的函数,让数字更小的具有更高的优先级,然后直接输出
代码
struct cmp{
bool operator()(ListNode* l, ListNode* r){
return l->val > r->val;
}
};
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, cmp> res;
for(int i = 0; i < lists.size(); ++i){
if(lists[i] != NULL){
res.push(lists[i]);
}
}
ListNode* start = new ListNode(0);
ListNode *curr = start;
ListNode *t = NULL;
while(!res.empty()){
t = res.top();
res.pop();
curr->next = t;
if(t->next != NULL){
res.push(t->next);
}
curr = curr->next;
}
return start->next;
}
};
Email:1252418308@qq.com