这题非常经典。
有4种解法。
- k个指针,每个指向一个list。每次比较k个指针的对应元素,取最小值,同时相应指针后移一位。如此反复直到所有list为空。
缺点是太慢,时间复杂度为O(k*N),N为所有元素。
代码如下:
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param lists: a list of ListNode
* @return: The head of one sorted list.
*/
ListNode *mergeKLists(vector<ListNode *> &lists) {
int listsSize = lists.size();
if (listsSize == 0) return nullptr;
ListNode dummy(ListNode(0));
ListNode *result = &dummy;
ListNode *head = result;
vector<ListNode *> listPtrs(listsSize);
set <int> s;
for (int i = 0; i < listsSize; ++i) {
s.insert(i);
listPtrs[i] = lists[i];
}
while (!s.empty()) {
int index = *(s.begin());
int minVal = INT_MAX;
if (listPtrs[index]) minVal = listPtrs[index]->val;
for (auto i : s) {
if (listPtrs[i]) {
if (listPtrs[i]->val <= minVal) { //note: should be <= here
index = i;
minVal = listPtrs[i]->val;
}
} else {
s.erase(i);
}
}
result->next = listPtrs[index];
result = result->next;
if (listPtrs[index]) listPtrs[index] = listPtrs[index]->next;
}
return head->next;
}
};
注意:
if (listPtrs[i]->val <= minVal) 这里必须用<= 而不是<,不过没想明白为什么<就不对?
看了一下网上类似的代码,发现我的代码较繁琐,其中的set和listPtrs[]都可以不用 ,用一个count就可以了。
2刷:还是繁琐
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int n = lists.size();
ListNode * dummyHead = new ListNode(INT_MAX);
vector<ListNode*> p(n);
for (int i = 0; i < n; ++i) {
p[i] = lists[i];
}
ListNode *candidate;
int smallest_value = INT_MAX, smallest_index = -1;
for (int i = 0; i < n; ++i) {
if (lists[i] && lists[i]->val <smallest_value) {
smallest_value = lists[i]->val;
smallest_index = i;
}
}
if (smallest_index == -1) return NULL;
candidate = lists[smallest_index];
dummyHead->next = candidate;
lists[smallest_index] = lists[smallest_index]->next;
while (1) {
smallest_value = INT_MAX, smallest_index = -1;
for (int i = 0; i < n; ++i) {
if (lists[i] && lists[i]->val < smallest_value) {
smallest_value = lists[i]->val;
smallest_index = i;
}
}
if (smallest_index == -1) break;
candidate->next = lists[smallest_index];
candidate = lists[smallest_index];
lists[smallest_index] = lists[smallest_index]->next;
}
return dummyHead->next;
}
};
下面这个代码写的较好。
https://algorithm.yuanbin.me/zh-hans/linked_list/merge_k_sorted_lists.html
-
k个lists,两两合并
参考https://zhuanlan.zhihu.com/p/56694331
TBD -
k个lists,从底向上merge(分治法)
参考https://zhuanlan.zhihu.com/p/56694331
TBD -
用最小堆。时间复杂度:假如总共有 N 个节点,每个节点入队出队都需要 log(k),所有时间复杂度是 O(N log(k))。
代码如下:
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
//bool operator > (const ListNode &a, const ListNode &b) { //最小堆
// return a.val > b.val;
//}
class cmp {
public:
bool operator() (ListNode* a, ListNode *b) {
return a->val > b->val;
}
};
class Solution {
public:
/**
* @param lists: a list of ListNode
* @return: The head of one sorted list.
*/
ListNode *mergeKLists(vector<ListNode *> &lists) {
int listsSize = lists.size();
if (listsSize == 0) return nullptr;
ListNode dummy(0);
ListNode *head = &dummy;
//priority_queue<ListNode *, vector<ListNode *>, greater<ListNode *>> pq;
priority_queue<ListNode *, vector<ListNode *>, cmp> pq;
for (auto ptr : lists) {
if (ptr) {
pq.push(ptr);
}
}
while(!pq.empty()) {
ListNode *node = pq.top();
cout<<"top.val="<<node->val<<endl;
pq.pop();
head->next = node;
head = node;
if (node->next) pq.push(node->next); //. has higher priority than *
}
return dummy.next;
}
};
二刷
struct cmp {
bool operator()(ListNode *a, ListNode *b) {
return a->val > b->val;
}
};
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int nRow = lists.size();
priority_queue<ListNode *, vector<ListNode *>, cmp> minHeap;
ListNode *head = new ListNode();
ListNode *origHead = head;
for (int i = 0; i < nRow; i++) {
if (lists[i]) {
minHeap.push(lists[i]);
}
}
while(!minHeap.empty()) {
ListNode *topNode = minHeap.top();
minHeap.pop();
head->next = topNode;
head = head->next;
if (topNode->next) minHeap.push(topNode->next);
}
return origHead->next;
}
};
三刷:注意decltype用法。
/**
* Definition of ListNode
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param lists: a list of ListNode
* @return: The head of one sorted list.
*/
ListNode *mergeKLists(vector<ListNode *> &lists) {
auto comp = [](ListNode *a, ListNode *b){ return a->val > b->val; };
priority_queue<ListNode *, vector<ListNode *>, decltype(comp)> minHeap(comp);
for (auto list : lists) {
if (list) minHeap.push(list);
}
ListNode *dummy = new ListNode(0), *node = dummy;
while (!minHeap.empty()) {
auto topNode = minHeap.top();
minHeap.pop();
if (topNode) {
node->next = new ListNode(topNode->val);
node = node->next;
if (topNode->next) minHeap.push(topNode->next);
}
}
return dummy->next;
}
};