23 - 合并K个排序链表 - python

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

示例:

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

题目要求合并给定的K个排序链表,K = 0,1, …, n,且每个链表中的元素可能有重复值。

  • 暴力法:首先遍历K个链表的每个结点,同时使用数组存储结点的值。然后将数组中的元素进行排序,最后使用排序后的数组构建结果链表。但这样的方法时间复杂度为 O ( k n ) + O ( n log ⁡ n ) + O ( k n ) O(kn) + O(n \log n) + O(kn) O(kn)+O(nlogn)+O(kn),效率太低。
class Solution(object):
    def mergeKLists(self, lists):
        if lists == []: return []

        r = []
        for l in lists:
            cur = l
            while cur:
                r.append(cur.val)
                cur = cur.next

        r = sorted(r)
        newHead = ListNode(-1)
        cur = newHead
        for i in r:
            cur.next = ListNode(i)
            cur = cur.next

        return newHead.next
  • 两两合并法:K个链表的合并和看成其两两合并后,使用前一个合并后的结果再和下一个链表合并,直到合并为K个链表。时间复杂度为 O ( k N ) O(kN) O(kN),效率依然不高。
class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        def merge(head1, head2):
            t = ListNode(-1)
            head = t
            while head1 and head2:
                if head1.val <= head2.val:
                    head.next = ListNode(head1.val)
                    head1 = head1.next
                else:
                    head.next = ListNode(head2.val)
                    head2 = head2.next    
                head = head.next

            if head1: head.next = head1
            if head2: head.next = head2

            return t.next
        
        if len(lists) == 0: return []
        if len(lists) == 1: return lists[0]

        newHead = None
        for i in range(0, len(lists) - 1):
            newHead = merge(newHead, lists[i])

        return newHead

一个比较优的做法是官方解答中给出的分治法

  • 将k个链表配对并将同一对中的链表合并
  • 第一轮合并后,K个链表被合并成 k 2 \frac{k}{2} 2k个链表,然后继续前一步分操作,直到得到最终的链表

    23 - 合并K个排序链表 - python_第1张图片
class Solution(object):
    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

合并K个排序链表

你可能感兴趣的:(Leetcode)