LeetCode题目(Python实现):合并K个排序链表

题目

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例 :

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

想法一:分治法

算法实现

def mergeKLists(self, lists: List[ListNode]) -> ListNode:
    n = len(lists)
    if n == 0:
        return None
    elif n == 1:
        return lists[0]
    i = 1
    while i < n:
        j = 0
        while j + i < n:
            lists[j] = self.mergeTwoLists(lists[j], lists[j + i])
            j += i * 2
        i *= 2
    return lists[0]


def mergeTwoLists(self,l1: ListNode, l2: ListNode) -> ListNode:
    prehead = ListNode(-1)
    prev = prehead
    while l1 and l2:
        if l1.val <= l2.val:
            prev.next = l1
            l1 = l1.next
        else:
            prev.next = l2
            l2 = l2.next
        prev = prev.next

    prev.next = l1 if l1 is not None else l2

    return prehead.next

执行结果

执行结果 : 通过
执行用时 : 88 ms, 在所有 Python3 提交中击败了93.60%的用户
内存消耗 : 16.5 MB, 在所有 Python3 提交中击败了44.78%的用户
在这里插入图片描述

复杂度分析

  • 时间复杂度:完蛋,自己分析不出来,尴尬,只能看官方了:O(kN) ,其中 k 是链表的数目。
  1. 我们可以在 O(n) 的时间内合并两个有序链表,其中 n 是两个链表的总长度。
  2. 把所有合并过程所需的时间加起来,我们可以得到:在这里插入图片描述
  • 空间复杂度:O(1),
    我们可以在 O(1) 空间内合并两个有序链表。

暴力法

算法实现

def mergeKLists(self, lists):
    """
    :type lists: List[ListNode]
    :rtype: ListNode
    """
    self.nodes = []
    head = point = ListNode(0)
    for l in lists:
        while l:
            self.nodes.append(l.val)
            l = l.next
    for x in sorted(self.nodes):
        point.next = ListNode(x)
        point = point.next
    return head.next

执行结果

在这里插入图片描述

复杂度分析

  • 时间复杂度:O(N log N) ,其中 N 是链表的数目。
  1. 遍历所有的值需花费 O(N)O(N) 的时间。
  2. 一个稳定的排序算法花费 O(N\log N)O(NlogN) 的时间。
  3. 遍历同时创建新的有序链表花费 O(N)O(N) 的时间。
  • 空间复杂度:O(N)
  1. 排序花费 O(N)O(N) 空间(这取决于你选择的算法)。
  2. 创建一个新的链表花费 O(N)O(N) 的空间。

分治法(官方)

算法实现

def mergeKLists(self, lists):
    """
    :type lists: List[ListNode]
    :rtype: ListNode
    """
    amount = len(lists)
    interval = 1
    while interval < amount:
        for i in range(0, amount - interval, interval * 2):
            lists[i] = self.merge2Lists(lists[i], lists[i + interval])
        interval *= 2
    return lists[0] if amount > 0 else lists


def merge2Lists(self, l1, l2):
    head = point = ListNode(0)
    while l1 and l2:
        if l1.val <= l2.val:
            point.next = l1
            l1 = l1.next
        else:
            point.next = l2
            l2 = l1
            l1 = point.next.next
        point = point.next
    if not l1:
        point.next = l2
    else:
        point.next = l1
    return head.next

执行结果

在这里插入图片描述

复杂度分析

同上

小结

先按照自己的想法设计,分治法每两个合并一次,第一次步长为1,第二次为2,第n次步长为2^(n-1),最后合并出结果,而合并两个有序链表之前已经写过函数,直接调用即可(调用的是迭代法)。

意外的是暴力法,没想到暴力法也有出头的一天,哈哈。

发布了112 篇原创文章 · 获赞 10 · 访问量 2898

猜你喜欢

转载自blog.csdn.net/qq_45556599/article/details/104784927
今日推荐