【数据结构-堆】【hard】力扣23. 合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 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 = [[]]

输出:[]

优先队列

csharp 复制代码
//正常情况优先队列如果true,表示当前元素比右侧元素小,将右侧元素放到堆顶,实现大根堆。
//改变operator后,当前元素比右侧元素大堆时候true,将右侧元素放到堆顶,实现小根堆。
class Solution {
public:
    struct Status {
        int val;
        ListNode *ptr;
        bool operator < (const Status &rhs) const {
            return val > rhs.val;
        }
    };

    priority_queue <Status> q;

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        for (auto node: lists) {
            if (node) q.push({node->val, node});
        }
        ListNode head, *tail = &head;
        while (!q.empty()) {
            auto f = q.top(); q.pop();
            tail->next = f.ptr; 
            tail = tail->next;
            if (f.ptr->next) q.push({f.ptr->next->val, f.ptr->next});
        }
        return head.next;
    }
};

时间复杂度 :考虑优先队列中的元素不超过 k 个,那么插入和删除的时间代价为 O(logk),这里最多有 kn 个点,对于每个点都被插入删除各一次,故总的时间代价即渐进时间复杂度为 O(kn×logk)。
空间复杂度:这里用了优先队列,优先队列中的元素不超过 k 个,故渐进空间复杂度为 O(k)。

我们定义了一个结构体Status,修改了他的比较器。正常情况优先队列如果true,表示当前元素比右侧元素小,将右侧元素放到堆顶,实现大根堆。
改变operator后,当前元素比右侧元素大堆时候true,将右侧元素放到堆顶,实现小根堆。

这道题是关于链表的题,题目要求合并k个升序链表,实际上我们就可以有这么一个思路:我们将每个链表的元素都丢入小根堆中,然后将小根堆的元素依次组成一个新的链表。由于题目中已经升序排列好每个链表,也就是说每个链表的头节点的val是链表中最小的。

首先我们先将lists中每个链表头节点push到小根堆q中,然后我们定义一个新链表头节点head,还有一个指针tail用来指向链表的尾部。接下来我们不断循环,f代表的是小根堆中的堆顶头节点,即val最小,我们将他连接到我们新建的链表尾部tail->next = f.ptr;,接着更新tail的位置tail = tail->next;使其在队尾。接着我们检查f节点的链表中是否还有其他节点,如果f.ptr->next存在,就将其连接的下一个节点推入到小根堆中,以便进行比较后插入到新建合并链表的合适位置。

最后返回head.next,这是因为head只是虚拟的头节点。

以及为什么我们不直接将节点的val一次性全部放入q中呢?因为当q的元素不断增加,插入的时间复杂度也在增加。堆的插入操作需要将元素插入到堆的最底层,并通过"上浮"操作将该元素移动到正确的位置。这个过程需要的时间复杂度是 O(log k),其中 k 是堆中元素的数量。

相关推荐
wen__xvn27 分钟前
每日一题洛谷P1428 小鱼比可爱c++
数据结构·c++·算法
小王努力学编程1 小时前
【C++篇】红黑树的实现
数据结构
酷酷的崽7981 小时前
【数据结构】—— 顺序表的实现与优化:空间管理与增容策略
c语言·数据结构
不玩return的马可乐2 小时前
LeeCode 1678. 设计 Goal 解析器
数据结构·c++·算法·leetcode·职场和发展
王旭·wangxu_a3 小时前
【例43.3】 转二进制
c语言·数据结构·c++·python·算法·蓝桥杯-算法提高·基础问题
张玉立5 小时前
C语言特殊操作符
c语言·数据结构·算法
の梦5 小时前
力扣209(2)——滑动窗口?!快慢指针的pro版罢了
java·数据结构·算法·leetcode·职场和发展·蓝桥杯
の梦5 小时前
力扣54题——螺旋矩阵
数据结构·算法·leetcode·职场和发展·矩阵·蓝桥杯
*TQK*6 小时前
C++/C语言判断重复数组(zznu)⭐
c语言·数据结构·c++