LeetCode23.合并k个有序链表

在这里插入图片描述

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 = [[]]
输出:[]

提示:

  • k == lists.length
  • 0 <= k <= 10^4
  • 0 <= lists[i].length <= 500
  • -10^4 <= lists[i][j] <= 10^4
  • lists[i] 按 升序 排列
  • lists[i].length 的总和不超过 10^4

💡解题思路

先看一下复杂度过高的思路:
在这里插入图片描述
对于这样一个例子,我们遍历lists,每次要找到所有升序链表中,要比较每一个升序头节点val,找到最小的那个尾插到结果链表(ans)
什么时候结束?
每一个lists[i]都为空,即所有的升序链表都找了一遍了,就结束
下面是这种解法的代码:是通不过的!时间复杂度太高!
在这里插入图片描述

优化? — > 采用优先级队列(priority_queue)

也就是我们创建一个小堆,以val的大小来排序
因为priority_queue的第三个参数需要传递一个仿函数,对于ListNode*类型我们需要自定义其行为,所以构建的仿函数如图:
在这里插入图片描述

整体思路

  • 创建一个优先级队列pq,优先级队列中存 ListNode*
  • 遍历lists,把每一个升序链表的头节点放入 pq
  • 每次取出top,即头节点val最小的链表的头指针
  • 然后pop一下,同时该头指针向后移动一部(tp = tp->next)
  • 如果该头指针向后走一步,仍不为空,重新push进队列
  • 当优先级队列为空,结束循环~

C++代码

 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;
    }
};
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值