Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
这道题是合并k个已排序链表,题目难度为Hard。
题目和21题(传送门)合并两个已排序链表相关,感兴趣的同学可以先看下21题。最直观的想法是将节点逐个存入堆中,然后再依次取出节点组建新的链表,这样题目就没什么难度了,关键在于堆的操作。这里用priority_queue来处理堆操作,priority_queue默认是大根堆,由于需要小根堆并且堆元素是指针,所以需要一个有自定义()操作的函数对象来作为比较函数。另外,堆还可以用STL中的make_heap()函数来实现。具体代码:
class Solution {
struct cmp {
bool operator()(ListNode* n1, ListNode* n2) {
return n1->val > n2->val;
}
};
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, cmp> heap;
ListNode* head = NULL;
ListNode* cur = NULL;
ListNode* pre = NULL;
for(auto list:lists) {
while(list) {
heap.push(list);
list = list->next;
}
}
if(heap.empty()) return head;
head = heap.top();
while(!heap.empty()) {
cur = heap.top();
heap.pop();
if(pre) pre->next = cur;
pre = cur;
}
cur->next = NULL;
return head;
}
};
还可以用分治法来解决这道题,将所有链表分成两部分,分别合并两部分的链表,然后再将合并后的两个链表合并为最终链表。这样就把问题通过分治法转化为合并两个已排序链表,即21题了。具体代码:
class Solution {
ListNode* mergeLists(const vector<ListNode*>& lists, int bgn, int end) {
if(bgn > end) return NULL;
if(bgn == end) return lists[bgn];
int mid = (bgn + end) / 2;
ListNode* l1 = mergeLists(lists, bgn, mid);
ListNode* l2 = mergeLists(lists, mid+1, end);
ListNode* head = NULL;
ListNode* prev = NULL;
if(!l1) return l2;
else if(!l2) return l1;
while(l1 && l2) {
if(l1->val > l2->val) {
if(!head) head = l2;
if(prev) {
prev->next = l2;
prev = l2;
}
else prev = l2;
l2 = l2->next;
}
else {
if(!head) head = l1;
if(prev) {
prev->next = l1;
prev = l1;
}
else prev = l1;
l1 = l1->next;
}
}
if(l1) prev->next = l1;
if(l2) prev->next = l2;
return head;
}
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
return mergeLists(lists, 0, lists.size()-1);
}
};