【力扣算法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


完结


相关文章
|
2天前
|
C语言 C++ 索引
力扣 138. 随机链表的复制
力扣 138. 随机链表的复制
|
2天前
|
算法
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)(下)
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)
7 1
|
2天前
|
算法 C++
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)(上)
数据结构与算法⑮(第四章_下)二叉树OJ(力扣:144,965,104,110,226,100,101,572)
7 1
|
2天前
|
机器学习/深度学习 存储 算法
数据结构与算法⑨(第三章_下)队列的概念和实现(力扣:225+232+622)(下)
数据结构与算法⑨(第三章_下)队列的概念和实现(力扣:225+232+622)
4 0
|
2天前
|
算法 前端开发 C语言
数据结构与算法⑨(第三章_下)队列的概念和实现(力扣:225+232+622)(上)
数据结构与算法⑨(第三章_下)队列的概念和实现(力扣:225+232+622)
11 0
|
2天前
|
缓存 算法 C语言
数据结构与算法⑧(第三章_上)栈的概念和实现(力扣:20. 有效的括号)
数据结构与算法⑧(第三章_上)栈的概念和实现(力扣:20. 有效的括号)
4 0
|
3天前
|
机器学习/深度学习 人工智能 算法
食物识别系统Python+深度学习人工智能+TensorFlow+卷积神经网络算法模型
食物识别系统采用TensorFlow的ResNet50模型,训练了包含11类食物的数据集,生成高精度H5模型。系统整合Django框架,提供网页平台,用户可上传图片进行食物识别。效果图片展示成功识别各类食物。[查看演示视频、代码及安装指南](https://www.yuque.com/ziwu/yygu3z/yhd6a7vai4o9iuys?singleDoc#)。项目利用深度学习的卷积神经网络(CNN),其局部感受野和权重共享机制适于图像识别,广泛应用于医疗图像分析等领域。示例代码展示了一个使用TensorFlow训练的简单CNN模型,用于MNIST手写数字识别。
18 3
|
3天前
|
算法 Python
Python中实现图论算法
Python中实现图论算法 “【5月更文挑战第20天】”
12 3
|
8天前
LeetCode链表hard 有思路?但写不出来?
LeetCode链表hard 有思路?但写不出来?
|
8天前
|
算法 搜索推荐 C语言
Python实现数据结构与算法
【5月更文挑战第13天】学习数据结构与算法能提升编程能力,解决复杂问题,助你面试成功。从选择资源(如《算法导论》、Coursera课程、LeetCode)到实践编码,逐步学习基本概念,通过Python实现栈、队列和快速排序。不断练习、理解原理,探索高级数据结构与算法,参与开源项目和算法竞赛,持续反思与实践,以提升技术能力。
6 0