LeetCode刷题记录 |
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。。
示例1
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例2
输入:lists = []
输出:[]
示例3:
输入:lists = [[]]
输出:[]
提示:
先看一下复杂度过高的思路:
对于这样一个例子,我们遍历lists,每次要找到所有升序链表中,要比较每一个升序头节点val,找到最小的那个尾插到结果链表(ans)
什么时候结束?
每一个lists[i]都为空,即所有的升序链表都找了一遍了,就结束
下面是这种解法的代码:是通不过的!时间复杂度太高!
优化? — > 采用优先级队列(priority_queue)
也就是我们创建一个小堆,以val的大小来排序
因为priority_queue的第三个参数需要传递一个仿函数,对于ListNode*
类型我们需要自定义其行为,所以构建的仿函数如图:
整体思路
pq
,优先级队列中存 ListNode*
lists
,把每一个升序链表的头节点放入 pq
top
,即头节点val最小的链表的头指针pop
一下,同时该头指针向后移动一部(tp = tp->next
)push
进队列 template<class T>
struct mygreater{
bool operator()(const T& x,const T& y){
return x->val > y->val;
}
};
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
ListNode* ans = new ListNode;
ListNode* ans_cur = ans;
//小堆
priority_queue<ListNode*,vector<ListNode*>,mygreater<ListNode*>> pq;
//把每一个节点放入小堆
for(auto i : lists){
if(i){
pq.push(i);
}
}
//开始合并
while(!pq.empty()){
//取top
ListNode* tp = pq.top();
pq.pop();
//最小尾插到ans
ans_cur->next=tp;
ans_cur = ans_cur->next;
//如果刚才的堆顶还不为空
tp = tp->next;
if(tp){
pq.push(tp);
}
}
return ans->next;
}
};