合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->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) {
ListNode* result= new ListNode(0);
ListNode* temph= result;
int index= 0, maxh= INT_MAX, size= lists.size();
while(true){
maxh= INT_MAX, index= -1;
// 找到最小的值和下标
for(int i= 0; i< size; ++i){
if(lists[i]&& lists[i]->val< maxh){
maxh= lists[i]->val;
index= i;
}
}
// 已经遍历完所有的链表
if(index== -1) break;
// 将最小值的节点存入结果链表
temph->next= lists[index];
temph= temph->next;
lists[index]= lists[index]->next;
}
return result->next;
}
};
参考Leetcode题解中的官方题解,使用优先队列来优化算法;
优先队列支持自动排序,其头部保存的是队列中值最小的节点,所以每次只要取队列的头部就可以了
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
class Node{
public:
int val;
ListNode* ptr;
Node(int v, ListNode* p){
val= v;
ptr= p;
}
// 重载运算符使优先队列按升序排列
bool operator < (const Node& n) const{
return val> n.val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
// 按升序排列的优先队列
priority_queue<Node> pq;
// 初始化优先队列
int size= lists.size();
for(int i= 0; i< size; ++i)
if(lists[i])
pq.push(Node(lists[i]->val, lists[i]));
ListNode* result= new ListNode(0), *temph= result;
Node temp= Node(0, NULL);
while(!pq.empty()){
// 优先队列中的最小值
temp= pq.top(), pq.pop();
temph->next= temp.ptr;
temph= temph->next;
if(temp.ptr->next) pq.push(Node(temp.ptr->next->val, temp.ptr->next));
}
return result->next;
}
};