leetcode23_Merge k Sorted Lists

橘子oly發表於2016-10-20

一.問題描述

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

合併k條有序連結串列,返回一條有序連結串列


二.演算法思想

有兩種思路:

1)利用二路歸併的思想,將k條有序鏈條兩兩進行二路歸併,一共需要logk次合併後得到最終連結串列。顯然,可以通過遞迴來實現 ,既然說到遞迴,那麼應該也可以考慮用時間換空間;

2)k個指標順序遍歷k條有序連結串列,每次取出來的節點組成一個堆(這裡考慮用堆,每次進行對排序只需要logk的複雜度,只需要取最大or最小值時要考慮用堆啊!!!不需要完全有序!),每次取堆頂接到輸出連結串列中,並繼續遍歷k條有序連結串列。

實現時注意,這種單連結串列的操作加上頭結點會比較好處理(避免過多的判斷語句)。


三.演算法實現

二路歸併的思想,沒有通過遞迴來實現,程式碼如下:

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def merge2Lists(self, listNodeA, listNodeB):
        i = listNodeA
        j = listNodeB
        return_listNode = ListNode(0)  # return node with a header
        return_aid = return_listNode
        while i != None and j != None:
            if i.val < j.val:
                return_aid.next = i
                i = i.next
            else:
                return_aid.next = j
                j = j.next
            return_aid = return_aid.next
        if i != None:
            return_aid.next = i
        elif j != None:
            return_aid.next = j
        return return_listNode.next

    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        k = len(lists)
        if k == 0: return []
        j = 1
        while j < k :
            for i in range(0, k, 2 * j):
                lists[i] = self.merge2Lists(lists[i], lists[i + j]) if i + j < k else lists[i]
            j *= 2
        return lists[0]
這個演算法效率並不高,可是我看了下程式碼本身並沒發現很多可優化的地方啊- -

用堆實現的演算法參見網站http://www.jiuzhang.com/solutions/merge-k-sorted-lists/ 程式碼如下:

class Solution:
    """
    @param lists: a list of ListNode
    @return: The head of one sorted list.
    """
    def mergeKLists(self, lists):
        # write your code here
        self.heap = [[i, lists[i].val] for i in range(len(lists)) if lists[i] != None]
        self.hsize = len(self.heap)
        for i in range(self.hsize - 1, -1, -1):
            self.adjustdown(i)
        nHead = ListNode(0)
        head = nHead
        while self.hsize > 0:
            ind, val = self.heap[0][0], self.heap[0][1]
            head.next = lists[ind]
            head = head.next
            lists[ind] = lists[ind].next
            if lists[ind] is None:
                self.heap[0] = self.heap[self.hsize-1]
                self.hsize = self.hsize - 1
            else:
                self.heap[0] = [ind, lists[ind].val]
            self.adjustdown(0)
        return nHead.next

    def adjustdown(self, p):
        lc = lambda x: (x + 1) * 2 - 1
        rc = lambda x: (x + 1) * 2
        while True:
            np, pv = p, self.heap[p][1]
            if lc(p) < self.hsize and self.heap[lc(p)][1] < pv:
                np, pv = lc(p), self.heap[lc(p)][1]
            if rc(p) < self.hsize and self.heap[rc(p)][1] < pv:
                np = rc(p)
            if np == p:
                break
            else:
                self.heap[np], self.heap[p] = self.heap[p], self.heap[np]
                p = np
但是實際上我用leetcode試著提交了上述程式碼,結果居然比我手寫的二路歸併思想的演算法效率還低。。。改天我要自己寫一個- -


相關文章