之前是合并两个,这次的题目是合并k个有序链表,当然也可以用两个的思路去做,比较每个链表中当前的那个值,把最小的加入返回链表中,最后得到的就是合并之后的链表。每一次合并都要检查所有的链表,最终时间复杂度是O(nk)
/**
* 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* res=new ListNode(0);
ListNode* p1=res;
int min=0;
int minpos=0;
int nullnum=0;
while(nullnum<lists.size()){
nullnum=0;
min=INT_MAX;
minpos=0;
for(int i=0;i<lists.size();i++){
if(lists[i]==nullptr){
nullnum++;
continue;
}
if(lists[i]->val<min){
min=lists[i]->val;
minpos=i;
}
}
if(nullnum==lists.size()) break;
ListNode* pdel=lists[minpos];
cout <<minpos <<endl<< nullnum;
lists[minpos]=lists[minpos]->next;
delete pdel;
p1->next=new ListNode(min);
p1=p1->next;
}
return res->next;
}
};
但是最终得分很不理想,只有5%。说明还有优化空间,而且最优的时间复杂度应该不是O(nk) 。分析程序我们发现,每一次循环,每一个链表的当前节点都要被检查一遍,如果上一次循环检查了这个节点而它又不是最小值,下一次循环就还要再检查一遍这个节点,导致大量的重复运算。
实际上,每次循环只要找出最小值,而只变化一个元素。这让我想到了一种数据结构:优先队列。有关优先队列的东西,推荐一篇文章:https://mp.weixin.qq.com/s?src=11×tamp=1584005226&ver=2212&signature=TcfPuKmUrwuqagQzMWvSwRPlN28zoM9E*AYiXQ4Rt2PhIlPP*0P1Wox3E02fQtpE4ALa9F3ZJGoQLO6XN*2mfOSeQtv9-ZIfnvuAa5gwKMYTx3mseEz-ZtCfQzVTqXol&new=1
优先队列实现非常简单,用一个数组就可以手撕。但是STL里面也有优先队列的实现,就不用我们自己去写了。
这个STL优先队列和我想象的非常不一样,写出这段代码的时候,我也查阅了不少关于C++STL中优先队列的资料。解释一下最重要的优先队列声明函数:
priority_queue是一个容器适配器,即把某个底层容器包装起来,好去模拟某种有新功能的数据结构。但这样也就丧失了底层容器的迭代器功能。priority_queue类模板需要提供三个参数:一个成员类型T,一个底层容器类型Container <T>,和一个比较函数Comp。底层容器默认用vector<T>,而比较函数默认用std::less函数,越大的优先级越高。你第一个例子priority_queue< int , vector<int> , greater<int> > que;意思是,这个priority_queue里的数据类型是int,它是用vector<int>作为底层容器实现,并且用系统提供的greater函数作为比较标准。于是越小的数优先级越高。第二个例子,目测不对,类型不一致。
其实这个greater并不是一个比较函数!而是一个类。类中还需要重载函数调用运算符()。至于为什么,我想之后再补充了。。。
总之代码就是这样,放一下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
struct cmp{
bool operator ()(ListNode* a,ListNode* b){
return a->val>b->val;
}
};
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
ListNode* res=new ListNode(0);
ListNode* p1=res;
ListNode* min;
priority_queue<ListNode*,vector<ListNode*>,cmp> heap;
for(int i=0;i<lists.size();i++){
if(lists[i]!=nullptr) heap.push(lists[i]);
}
while(!heap.empty()){
min = heap.top();
heap.pop();
if(min!=nullptr&&min->next!=nullptr) heap.push(min->next);
p1->next=new ListNode(min->val);
delete min;
p1=p1->next;
}
return res->next;
}
};
最后,可算是拿到一个可以的分数了,发一下图:
顺便吐槽奇葩输入,我就知道会有这一组数据来坑人!