1. 程式人生 > 實用技巧 >Leetcode 23 Merge k Sorted Lists

Leetcode 23 Merge k Sorted Lists

題目介紹

合併k個已經排序的連結串列。

Example:

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6

Solutions

常規解法

常規解法,使用遍歷,缺點就是十分的慢:

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        dummy = ListNode(0)
        p = dummy
        k = len(lists)
        while True:
            val = float('inf')
            index = -1
            for i in range(k):
                if lists[i]:
                    if lists[i].val < val:
                        val = lists[i].val
                        index = i
            if index == -1:
                return dummy.next
            p.next = lists[index]
            p = p.next
            lists[index] = lists[index].next

優先佇列

每次都將(node.val, node)加入佇列:

from Queue import PriorityQueue
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        dummy = ListNode(0)
        p = dummy
        q = PriorityQueue()
        for i in range(len(lists)):
            if lists[i]:
                q.put((lists[i].val, lists[i]))
        while not q.empty():
            cur = q.get()[1]
            p.next, p = cur, cur
            if cur.next:
                q.put((cur.next.val, cur.next))
        return dummy.next

需要注意的是:

p.next = cur
p = p.next

不能表示為:
p.next, p = cur, p.next
因為會產生一箇中間變數p.next,而不是已經賦值為curp.next。例如:

>>> a, b = 1, 2
>>> a, b = a+b, a
>>> a
3
>>> b
1

這種特點可以很方便的解決連結串列的問題,例如:leetcode 24 Swap Nodes in Pairs

class Solution(object):
    def swapPairs(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        dummy = ListNode(0)
        dummy.next = head
        prev, p = dummy, head
        while p and p.next:
            # 0. 原始序列0->1->2->3->4
            # 1. 節點p的下個節點指向下個節點的下個節點,1->3
            # 2. 節點p指向下一個節點,p為2
            # 3. 節點p的下個節點指向p,2->1
            # 綜上,節點p一直都是以前的變數,可以看做temp=p,操作的都是temp
            p.next, p, p.next = p.next.next, p.next, p
            # 同理,此時p=2, 0->2後,prev=1,p=3
            prev.next, prev, p = p, p.next, p.next.next
        return dummy.next

與使用優先佇列類似,也可以使用最小堆:

from heapq import *
class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        dummy = ListNode(0)
        p = dummy
        q = []
        for i in range(len(lists)):
            if lists[i]:
                heappush(q, (lists[i].val, lists[i]))
        while q:
            cur = heappop(q)[1]
            p.next, p = cur, cur
            if cur.next:
                heappush(q, (cur.next.val, cur.next))
        return dummy.next