23. 合并K个排序链表

2020-02-02  本文已影响0人  oneoverzero

题目描述:

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

示例:

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

优先级队列的概念:

参考:

优先级队列与普通队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。优先级队列底层是用堆实现的。

Python的PriorityQueue是用 heapq 实现的。( https://blog.csdn.net/liu2012huan/article/details/53264162

代码:

from Queue import PriorityQueue
# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        q = PriorityQueue(maxsize=len(lists))
        cur = dummy = ListNode(None)
        for idx, node in enumerate(lists):
            if node:
                q.put((node.val, idx, node))
        while q.qsize() > 0:
            _, idx, cur.next = q.get() # get()会将节点弹出
            cur = cur.next
            if cur.next:
                q.put((cur.next.val, idx, cur.next))
        return dummy.next

这里有一些细节需要注意:

复杂度分析:(强烈建议参考: https://blog.csdn.net/hellozhxy/article/details/81055397

前已述及,优先级队列的底层是用堆实现的。因此往一个长度为 n 的优先级队列中插入一个元素的时间复杂度为 O(\log n) 。如果总共有 m 个元素,则将这 m 个元素插入这个长度为 n 的优先级队列中的时间复杂度为 O(m \log n)

现在代码中优先级队列的最大长度为 k ,把最初的 k 个头结点插入这个优先级队列的时间复杂度为 O(k \log k)

关于时间复杂度的分析,@ gulshan98125 认为:假设 n 是所有链表中最长的链表长度,现在总共有 k 个链表,则总的时间复杂度为 O(nk \log k) ;而 @spitza 认为,把 n 当成是 k 个链表中所有的节点个数显得更直观一些,这样一来时间复杂度将会变成 O(n \log k) 。我个人的观点是,把 n 当成是这 k 个链表的平均长度,这样时间复杂度为 O(nk \log k)

空间消耗在于维护一个长度为 k 的优先级队列(其实是维护一个容量为 k 的堆),因此空间复杂度为 O(k)

上一篇 下一篇

猜你喜欢

热点阅读