【力扣算法04】之合并 K 个升序链表- python

简介: 【力扣算法04】之合并 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

思路分析

  1. 首先,定义一个辅助方法 mergeTwoLists,用于将两个有序链表合并成一个有序链表。
  2. 接着,定义一个辅助方法 mergeKListsHelper,该方法接收一个链表数组 lists、起始索引 start 和结束索引 end,返回合并后的链表。
  3. mergeKListsHelper 方法中,首先判断起始索引 start 是否大于结束索引 end,如果是,则直接返回 None
  4. 然后,判断起始索引 start 是否等于结束索引 end,如果是,则说明只有一个链表需要合并,直接返回该链表即可。
  5. 如果起始索引 start 小于结束索引 end,则计算中间索引 mid,将链表数组拆分成两个部分。
  6. 调用递归方法 mergeKListsHelper,分别传入起始索引 start 和中间索引 mid,得到合并后的左半部分链表。
  7. 同样地,调用递归方法 mergeKListsHelper,分别传入中间索引 mid+1 和结束索引 end,得到合并后的右半部分链表。
  8. 最后,调用辅助方法 mergeTwoLists,将左半部分链表和右半部分链表合并成一个有序链表,并返回合并后的结果。
  9. 最后,在主方法 mergeKLists 中,判断链表数组 lists 是否为空,如果为空,则直接返回 None
  10. 否则,调用辅助方法 mergeKListsHelper,传入链表数组 lists、起始索引0 和结束索引 len(lists)-1,得到最终合并后的链表。

代码分析

第1块:

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """

定义了一个名为 Solution 的类,该类包含一个方法 mergeKLists,接收一个参数 lists,并且没有指定返回类型。

第2块:

if not lists:
    return None

判断链表数组 lists 是否为空,如果为空,则直接返回 None

第3块:

n = len(lists)

获取链表数组 lists 的长度,并将其赋值给变量 n

第4块:

while n > 1:
    k = (n + 1) // 2
    for i in range(n // 2):
        lists[i] = self.mergeTwoLists(lists[i], lists[i+k])
    n = k

使用循环进行链表的合并操作。首先判断 n 是否大于1,即还有多个链表需要合并。然后计算中间位置的索引并赋值给变量 k。接着使用循环遍历链表数组的前一半元素的索引,调用辅助方法 mergeTwoLists 对当前元素和对应的后半部分元素进行合并,并将结果赋值给当前元素。最后将数组长度更新为中间位置,并继续下一轮循环。

第5块:

return lists[0)

返回合并后的链表数组的第一个元素,即最终合并后的链表。

第6块:

def mergeTwoLists(self, l1, l2):
    if not l1:
        return l2
    if not l2:
        return l1
    if l1.val < l2.val:
        l1.next = self.mergeTwoLists(l1.next, l2)
        return l1
    else:
        l2.next = self.mergeTwoLists(l1, l2.next)
        return l2

定义了一个辅助函数 mergeTwoLists,接收两个参数 l1l2。该函数用于合并两个有序链表。首先判断链表 l1 是否为空,如果为空,则直接返回链表 l2。然后判断链表 l2 是否为空,如果为空,则直接返回链表 l1。接着判断链表 l1 的头结点的值是否小于链表 l2 的头结点的值。如果成立,将链表 l1 的下一个节点和链表 l2 传入递归调用的 mergeTwoLists 方法,并将返回的结果赋值给链表 l1 的下一个节点,并返回链表 l1。如果不成立,则将链表 l1 和链表 l2 的下一个节点传入递归调用的 mergeTwoLists 方法,并将返回的结果赋值给链表 l2 的下一个节点,并返回链表 l2


完整代码


class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        if not lists:  # 如果链表列表为空
            return None  # 返回 None
        n = len(lists)  # 获取链表列表的长度,并赋值给变量 n
        while n > 1:  # 当链表列表的长度大于 1 时,进行循环操作
            k = (n + 1) // 2  # 计算中间位置 k
            for i in range(n // 2):  # 对于每个索引 i,进行以下操作
                lists[i] = self.mergeTwoLists(lists[i], lists[i+k])  # 将 lists[i] 和 lists[i+k] 进行合并,并赋值给 lists[i]
            n = k  # 将 n 更新为 k,继续下一轮循环
        return lists[0]  # 返回合并后的链表列表的第一个元素,即最终合并后的链表
    def mergeTwoLists(self, l1, l2):
        if not l1:  # 如果 l1 为空
            return l2  # 直接返回 l2
        if not l2:  # 如果 l2 为空
            return l1  # 直接返回 l1
        if l1.val < l2.val:  # 如果 l1 的头结点的值小于 l2 的头结点的值
            l1.next = self.mergeTwoLists(l1.next, l2)  # 将 l1 的下一个节点与递归调用的 self.mergeTwoLists(l1.next, l2) 结果进行合并,并赋值给 l1.next
            return l1  # 返回 l1
        else:  # 否则
            l2.next = self.mergeTwoLists(l1, l2.next)  # 将 l1 和 l2 的下一个节点与递归调用的 self.mergeTwoLists(l1, l2.next) 结果进行合并,并赋值给 l2.next
            return l2  # 返回 l2

额外讲解


  1. class Solution(object)::定义了一个名为 Solution 的类。
  2. def mergeKLists(self, lists)::定义了一个方法 mergeKLists,接收一个参数 lists
  3. if not lists::判断链表数组 lists 是否为空。如果为空,则直接返回 None
  4. n = len(lists):获取链表数组的长度。
  5. while n > 1::进入循环,条件是链表数组的长度大于1,即还有多个链表需要合并。
  6. k = (n + 1) // 2:计算中间位置的索引。
  7. for i in range(n // 2)::遍历链表数组的前一半元素的索引。
  8. lists[i] = self.mergeTwoLists(lists[i], lists[i+k]):调用辅助方法 mergeTwoLists,将当前元素和对应的后半部分元素进行合并,并将结果赋值给当前元素。
  9. n = k:更新链表数组的长度为中间位置。
  10. return lists[0]:返回合并后的链表数组的第一个元素,也就是最终合并后的链表。
  11. def mergeTwoLists(self, l1, l2)::定义了一个辅助函数 mergeTwoLists,接收两个参数 l1l2
  12. if not l1::判断链表 l1 是否为空。如果为空,则直接返回 l2
  13. if not l2::判断链表 l2 是否为空。如果为空,则直接返回 l1
  14. if l1.val < l2.val::判断链表 l1 的头结点的值是否小于链表 l2 的头结点的值。
  15. l1.next = self.mergeTwoLists(l1.next, l2):递归调用 mergeTwoLists 方法,将 l1 的下一个节点和 l2 传入,并将返回的结果赋值给 l1 的下一个节点。
  16. return l1:返回合并后的链表 l1
  17. else::如果链表 l1 的头结点的值大于等于链表 l2 的头结点的值。
  18. l2.next = self.mergeTwoLists(l1, l2.next):递归调用 mergeTwoLists 方法,将 l1l2 的下一个节点传入,并将返回的结果赋值给 l2 的下一个节点。
  19. return l2:返回合并后的链表 l2


完结


相关文章
|
算法 Go
【LeetCode 热题100】23:合并 K 个升序链表(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 23——合并 K 个升序链表的两种解法:优先队列(最小堆)和分治合并。题目要求将多个已排序链表合并为一个升序链表。最小堆方法通过维护节点优先级快速选择最小值,;分治合并则采用归并思想两两合并链表。文章提供了 Go 语言实现代码,并对比分析两种方法的适用场景,帮助读者深入理解链表操作与算法设计。
433 10
|
存储 Python
Python 实现单向链表,和单向链表的反转
链表是一种数据结构,每个节点存储相邻节点的位置信息。单链表中的节点仅存储下一节点的位置。通过Python实现单链表,定义`ListNode`类并关联节点可创建链表。例如,创建A-&gt;B-&gt;C的链表后,可通过反转函数`reverse`将链表反转为CBA。代码展示了如何实现和操作单链表。
321 6
Python 实现单向链表,和单向链表的反转
|
存储 Python
Python 中链表的个人理解
简介:本文介绍了Python中链表的基本组成及其操作实现。链表由`head`(头节点)、中间节点和`tail`(尾节点)三部分构成,每个节点通过`Node`类定义,包含`value`(值域)和`next`(指针域)。示例代码展示了链表的增删查功能,包括`add`(头部插入)、`append`(尾部插入)、`remove`(删除节点)、`search`(查找节点)及遍历方法。运行结果验证了链表操作的正确性。
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
511 30
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
752 25
|
存储 监控 算法
员工电脑监控系统中的 C# 链表算法剖析-如何监控员工的电脑
当代企业管理体系中,员工电脑监控已成为一个具有重要研究价值与实践意义的关键议题。随着数字化办公模式的广泛普及,企业亟需确保员工对公司资源的合理利用,维护网络安全环境,并提升整体工作效率。有效的电脑监控手段对于企业实现这些目标具有不可忽视的作用,而这一过程离不开精妙的数据结构与算法作为技术支撑。本文旨在深入探究链表(Linked List)这一经典数据结构在员工电脑监控场景中的具体应用,并通过 C# 编程语言给出详尽的代码实现与解析。
246 5
|
12月前
|
存储 算法 物联网
解析局域网内控制电脑机制:基于 Go 语言链表算法的隐秘通信技术探究
数字化办公与物联网蓬勃发展的时代背景下,局域网内计算机控制已成为提升工作效率、达成设备协同管理的重要途径。无论是企业远程办公时的设备统一调度,还是智能家居系统中多设备间的联动控制,高效的数据传输与管理机制均构成实现局域网内计算机控制功能的核心要素。本文将深入探究 Go 语言中的链表数据结构,剖析其在局域网内计算机控制过程中,如何达成数据的有序存储与高效传输,并通过完整的 Go 语言代码示例展示其应用流程。
238 0
|
存储 监控 算法
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
在数字化办公时代,公司监控上网软件成为企业管理网络资源和保障信息安全的关键工具。本文深入剖析C++中的链表数据结构及其在该软件中的应用。链表通过节点存储网络访问记录,具备高效插入、删除操作及节省内存的优势,助力企业实时追踪员工上网行为,提升运营效率并降低安全风险。示例代码展示了如何用C++实现链表记录上网行为,并模拟发送至服务器。链表为公司监控上网软件提供了灵活高效的数据管理方式,但实际开发还需考虑安全性、隐私保护等多方面因素。
278 0
公司监控上网软件架构:基于 C++ 链表算法的数据关联机制探讨
|
存储 算法 搜索推荐
Python 实现反转、合并链表有啥用?
大家好,我是V哥。本文介绍Python实现反转链表和合并链表的应用场景及代码实现。反转链表适用于时间序列数据展示、回文链表判断等;合并链表则用于大规模数据排序、数据库查询结果集合并等。通过迭代和递归方法实现反转链表,以及合并两个或多个有序链表的算法,帮助开发者解决实际问题。关注V哥,了解更多实用编程技巧。 先赞再看后评论,腰缠万贯财进门。
286 0
|
Python
探索 Python 中链表的实现:从基础到高级
链表是一种由节点组成的基础数据结构,每个节点包含数据和指向下一个节点的引用。本文通过Python类实现单向链表,详细介绍了创建、插入、删除节点等操作,并提供示例代码帮助理解。链表在处理动态数据时具有高效性,适用于大量数据变动的场景。文章为初学者提供了全面的入门指南,助你掌握链表的核心概念与应用。
779 0

推荐镜像

更多
下一篇
开通oss服务