LeetCode23.合并k个有序链表

在这里插入图片描述

LeetCode刷题记录

文章目录

    • 题目描述
    • 解题思路
    • C++代码


题目描述

给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。。

示例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

解题思路

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

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

也就是我们创建一个小堆,以val的大小来排序
因为priority_queue的第三个参数需要传递一个仿函数,对于ListNode*类型我们需要自定义其行为,所以构建的仿函数如图:
LeetCode23.合并k个有序链表_第3张图片

整体思路

  • 创建一个优先级队列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;
    }
};

你可能感兴趣的:(LeetCode,链表,数据结构)