问题描述:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
问题分析:
和21题一样,两个有序链表合并和K个有序链表合并思路一致。
1)本题可以利用Merge Two Sorted Lists,用二分法,先两两合并,规模就缩小了原来的一半,然后采用递归
2)更好的办法是利用优先队列,把每个List的第一个节点放进队列,然后取出队列的最大节点,然后将其next放如队列。
一开始采用如下程序,提示超时
/**
* 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) {
ListNode *p = lists[0];
int len = lists.size();
if(len == 0)
return NULL;
for(int i = 1; i < len; i++){
p = mergeTwoLists(p, lists[i]);
}
return p;
}
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
if (l1 == NULL)
return l2;
if (l2 == NULL)
return l1;
ListNode *start, *p1;
if (l1->val < l2->val) {
p1 = start = l1;
l1 = l1->next;
} else {
p1 = start = l2;
l2 = l2->next;
}
while (l1 != NULL && l2 != NULL) {
if (l1->val < l2->val) {
p1->next = l1;
p1 = l1;
l1 = l1->next;
} else {
p1->next = l2;
p1 = l2;
l2 = l2->next;
}
}
if (l1 != NULL)
p1->next = l1;
else
p1->next = l2;
return start;
}
};
问题求解一:
以下是二分法求解
/**
* 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) {
int sz = lists.size();
if (sz == 0)
return NULL;
while (sz > 1) {
int k = (sz + 1) / 2;
for (int i = 0; i < sz / 2; i++)
lists[i] = mergeTwoLists(lists[i], lists[i + k]);
sz = k;
}
return lists[0];
}
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
if (l1 == NULL)
return l2;
if (l2 == NULL)
return l1;
ListNode *start, *p1;
if (l1->val < l2->val) {
p1 = start = l1;
l1 = l1->next;
} else {
p1 = start = l2;
l2 = l2->next;
}
while (l1 != NULL && l2 != NULL) {
if (l1->val < l2->val) {
p1->next = l1;
p1 = l1;
l1 = l1->next;
} else {
p1->next = l2;
p1 = l2;
l2 = l2->next;
}
}
if (l1 != NULL)
p1->next = l1;
else
p1->next = l2;
return start;
}
};
问题求解二:
采用分治法
/**
* 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) {
vector<ListNode*>::iterator it;
for(it = lists.begin(); it!=lists.end(); ){
if(*it == NULL) it = lists.erase(it);
else it++;
}
if(lists.size()<=1) return lists.size()==0?NULL:lists[0];
ListNode* res = divide(lists, 0, lists.size()-1);
return res;
}
ListNode *divide(vector<ListNode*>& lists, int a, int b){
if(a==b) return lists[a];
int m = (a+b)/2;
ListNode* l1 = NULL, *l2 = NULL, *l3 = NULL, *res = NULL;
l1 = divide(lists, a, m);
l2 = divide(lists, m+1, b);
if(l1->val<l2->val){
l3 = l1; l1=l1->next;
}
else{
l3 = l2; l2=l2->next;
}
res = l3;
while(l1&&l2){
if(l1->val<l2->val){
l3->next = l1;
l1 = l1->next;
l3 = l3->next;
}
else{
l3->next = l2;
l2 = l2->next;
l3 = l3->next;
}
}
if(l1) l3->next = l1;
if(l2) l3->next = l2;
return res;
}
};
问题求解三:
struct compare {
bool operator()(const ListNode* l, const ListNode* r) {
return l->val > r->val;
}
};
ListNode *mergeKLists(vector<ListNode *> &lists) { //priority_queue
priority_queue<ListNode *, vector<ListNode *>, compare> q;
for(auto l : lists) {
if(l) q.push(l);
}
if(q.empty()) return NULL;
ListNode* result = q.top();
q.pop();
if(result->next) q.push(result->next);
ListNode* tail = result;
while(!q.empty()) {
tail->next = q.top();
q.pop();
tail = tail->next;
if(tail->next) q.push(tail->next);
}
return result;
}
关于标准库的优先队列请参照C++ STL priority_queue ,需要了解的是priority_queue在默认情况下是大顶椎,上面代码中q是小顶椎。