23.合并k个升序链表 python

题目

题目描述

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

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

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

题目链接

合并k个升序链表

题解

解题思路

为了将多个已经按升序排列的链表合并成一个升序链表,我们采用最小堆(或优先队列)的方法来高效地管理来自不同链表的节点,并始终以 O(log k) 的时间复杂度获取下一个最小元素,其中 k 是链表的数量。下面是详细的步骤:

  1. 定义链表节点类:首先定义 ListNode 类表示链表节点,每个节点包含一个整数值 val 和指向下一个节点的指针 next

  2. 初始化最小堆:创建一个最小堆(使用 Python 的 heapq 模块),用于存储链表头节点的值、唯一索引和节点本身。这里引入唯一索引是为了确保即使两个节点有相同的值,它们也是可比较的,从而避免了直接比较 ListNode 实例时可能出现的问题。

  3. 构建最小堆:遍历给定的链表数组 lists,对于每一个非空链表的头节点,将其值、唯一索引以及节点对象作为一个元组加入到最小堆中。同时,维护一个唯一的索引计数器,以确保每个插入堆中的元组都有不同的索引。

  4. 创建结果链表的虚拟头节点:创建一个虚拟头节点 dummy 作为结果链表的起始点,并用一个指针 current 来跟踪当前操作的位置。

  5. 提取最小值并维护堆

    • 当最小堆不为空时,从堆中弹出具有最小值的节点元组。
    • 将弹出的节点连接到结果链表中,更新 current 指针指向新添加的节点。
    • 如果弹出节点有后续节点,则将后续节点的值、新的唯一索引以及节点本身作为一个元组重新加入到最小堆中,继续维持堆的性质。
  6. 返回结果链表:当所有节点都已处理完毕后,即最小堆为空时,所有的节点都已经按照升序被添加到了结果链表中。此时返回由虚拟头节点 dummynext 属性指向的真实头节点,即为最终合并后的升序链表。

这种方法的时间复杂度大约是 O(N log k),其中 N 是所有链表中节点的总数,而 k 是链表的数量。空间复杂度取决于最小堆的大小,即 O(k),因为堆中最多会同时存放 k 个节点。通过这种方式,我们可以高效地将多个有序链表合并为一个有序链表。

关键点

  • 使用最小堆来保证每次都能得到当前未处理节点中的最小值。
  • 通过在堆中存储 (node.val, index, node) 元组的方式,确保即使两个节点的值相同也能正确比较,这里的 index 是一个递增的唯一标识符。
  • 创建一个虚拟头节点简化了对结果链表的操作,不需要特别处理链表为空的情况。

Python 实现

def mergeKLists(lists):
    min_heap = []
    dummy = ListNode()
    current = dummy
    index = 0  
    for node in lists:
        if node is not None:
            heappush(min_heap, (node.val, index, node))
            index += 1
    while min_heap:
        _, _, smallest_node = heappop(min_heap)
        current.next = smallest_node
        current = current.next
        if smallest_node.next:
            index += 1
            heappush(min_heap, (smallest_node.next.val, index, smallest_node.next))
    return dummy.next

我们向最小堆中插入的是一个三元组 (node.val, index, node),其中 index 是一个唯一索引,用来保证即使两个节点有相同的值,它们也是可比较的。这是因为 Python 在比较元组时,会按顺序比较每一个元素,直到找到不同的元素为止。通过这种方式,我们可以确保最小堆总是能够正确地比较和排序链表节点。

提交结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gxls2024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值