Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

这是一道hard的题目,但是其实思路并不复杂,做起来也比较有趣。做完Merge Two Sorted Lists再做这道题,很容易觉得修改Merge Two中的思路就可以再做这道题。Merge k 与Two主要的不同点在于Merge K一次最多需要比较K个结点,复杂度比较高,而且每次比完之后,移除最小的,加入新元素需要继续比较,k-1个元素本身不变,很自然而然的想到使用堆来做。结合题目的需要,需要比较K个元素取得最小的元素,应该使用最小堆。python 中使用heapq这个模块。每次比较复杂度为O(logk).一共需要比较nk次,所以复杂度为nkO(logk)。空间复杂度为O(1)(堆的大小最大为k),代码如下:

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        if not lists:
            return None
        if len(lists) == 1:
            return lists[0]
        dummy = ListNode(-1)
        cur = dummy 
        pq = [(n.val,n) for n in lists if n]
        heapq.heapify(pq)
        while pq:
            n = pq[0][1]
            if not n.next:
                heapq.heappop(pq)
            else:
                heapq.heapreplace(pq,(n.next.val,n.next))
            cur.next = n 
            cur = cur.next
        return dummy.next

需要注意的是,这里heapq中存入的元素为结构元素,而不是直接的值,可以将每个结点使用tuple表示,元组中的第一个值为比较的键值,否则会一直超时。

这题还有另外一个思路,即二分,递归调用Merge Two Lists。即先将Lists两两合并,将合并的结果继续两两合并。复杂度为:

2n*(k/2)+4n*(k/4)+8n*(k/8)+....=nklog(k).其中(k/2),(k/2)为每次合并的次数。具体代码可以有递归和迭代两种写法。

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        if not lists:
            return None
        pq = []
        for i in xrange(len(lists)):
            cur = lists[i]
            if cur:
                heapq.heappush(pq,(cur.val,cur))
        pre = dummy = ListNode(-1)
        while pq:
            cur = heapq.heappop(pq)[1]
            pre.next = cur
            pre = pre.next
            cur = cur.next
            if cur:
                heapq.heappush(pq,(cur.val,cur))
        return dummy.next
        

 

posted on 2016-04-24 16:36  Sheryl Wang  阅读(156)  评论(0编辑  收藏  举报

导航