23. 合并K个排序链表
1.题目描述
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
2.方法1(优先队列)
把K个链表的头节点放到优先队列里面,则优先队列出队的是当前最小元素,接到结果链表里面,如果最小元素的下一个节点非空,则把该节点入队,重复这个过程,当队列为空时,则合并完毕。
3.代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
struct cmp{
bool operator()(ListNode* l1, ListNode* l2){
return l1->val > l2->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*,vector<ListNode*>,cmp> pri_q;
for(auto l : lists){
if(l){
pri_q.push(l);
}
}
ListNode* dummy_head = new ListNode(0);
ListNode* head = dummy_head;
while(!pri_q.empty()){
ListNode* node = pri_q.top();
pri_q.pop();
head->next = node;
head = node;
if(node->next != NULL){
pri_q.push(node->next);
}
}
return dummy_head->next;
}
};
4.复杂度分析
时间复杂度:O(nlogK),n是所有节点个数,K为链表个数。
空间复杂度:O(K)
5.方法2(分治法)
1.k个链表两两配对,进行第一轮合并,结束后k个链表被合并成k/2个链表
2.k/2个链表依然两两配对,进行第二轮合并,结束后k/2个链表被合并成k/4个链表
3.重复上述过程,进行log(k)次合并,完成总体合并工作
6.代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.empty()){
return NULL;
}
return merge(lists,0,lists.size() - 1);
}
ListNode* merge(vector<ListNode*>& lists,int begin, int end){
if(begin == end){
return lists[begin];
}
int mid = (begin + end) / 2;
ListNode* l1 = merge(lists,begin,mid);
ListNode* l2 = merge(lists,mid+1,end);
return mergeSort(l1,l2);
}
ListNode* mergeSort(ListNode* l1,ListNode* l2){
if(l1 == NULL){
return l2;
}
if(l2 == NULL){
return l1;
}
if(l1->val <= l2->val){
l1->next = mergeSort(l1->next,l2);
return l1;
}
else{
l2->next = mergeSort(l1,l2->next);
return l2;
}
}
};
7.复杂度分析
时间复杂度:O(nlogK)
空间复杂度:O(n)