【数据结构-堆】【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 是堆中元素的数量。

相关推荐
Lei_33596719 小时前
[算法]十大排序
数据结构·算法·排序算法
yuuki23323319 小时前
【数据结构】顺序表+回调函数
c语言·数据结构·后端
大数据张老师19 小时前
数据结构——堆排序
数据结构·算法·排序算法
画个逗号给明天"19 小时前
C++十大排序算法
数据结构·c++·排序算法
仰泳的熊猫19 小时前
LeetCode:268. 丢失的数字
数据结构·c++·算法·leetcode
VT.馒头19 小时前
【力扣】2725. 间隔取消
javascript·leetcode·1024程序员节
小龙报20 小时前
《算法通关指南数据结构和算法篇(3)--- 栈和stack》
开发语言·数据结构·c++·算法·创业创新·学习方法·visual studio
yy_xzz21 小时前
【数据结构】大话单链表
数据结构·链表
澪吟21 小时前
算法性能的核心度量:时间复杂度与空间复杂度全解析
数据结构·算法
咪咪渝粮1 天前
108. 将有序数组转换为二叉搜索树
算法·leetcode