1. 程式人生 > >LeetCode23-合併k個有序連結串列

LeetCode23-合併k個有序連結串列

今天白天沒課

自己還是早早的就過來了

上午刷了一道題之後

還是一如既往的看了一場我詹的比賽

下午上黨課

晚上在實驗室做應用數理統計的題目時

突然在想

自己每天都在幹嘛

每天都泡在實驗室都幹了些什麼

覺得自己忙活了一天

但收穫太少

深深地恐懼

有人說:當你有這種感覺的時候說明你還年輕

我亦不清楚

但我知道的是

明天早上起來吃一個梅乾菜和魚香肉絲的包子

對我來說就又是新的一天啦


23-合併k個有序連結串列

合併 個排序連結串列,返回合併後的排序連結串列。請分析和描述演算法的複雜度。

示例:

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

這一題與前面求合併2個有序連結串列極其類似,因此我當時做這題的時候第一想法就是借鑑前面求合併2個有序連結串列的方法,即不停的遍歷2個連結串列,最終肯定能得到結果的,但是執行效率太低了,基本上是5000ms以上了。

程式碼如下:

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        l_new = ListNode(0)
        if len(lists) == 0:
            return []
        if len(lists) == 1:
            return lists[0]
        l_new.next = self.mergeTwoLists(lists[0], lists[1])
        if len(lists) == 2:
            return l_new.next
        for index in range(2, len(lists)):
            l_new.next = self.mergeTwoLists(l_new.next, lists[index])
        return l_new.next

    def mergeTwoLists(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        l1_copy = l1
        l2_copy = l2
        combination = ListNode(0)
        com_copy = combination
        while l1_copy and l2_copy:
            if l1_copy.val <= l2_copy.val:
                com_copy.next = l1_copy
                l1_copy = l1_copy.next
                com_copy = com_copy.next
            else:
                com_copy.next = l2_copy
                l2_copy = l2_copy.next
                com_copy = com_copy.next
        if l1_copy and not l2_copy:
            com_copy.next = l1_copy
        elif not l1_copy and l2_copy:
            com_copy.next = l2_copy
        return combination.next


if __name__ == "__main__":
    l1 = ListNode(0)
    l1_copy = l1
    l2 = ListNode(0)
    l2_copy = l2
    l1_num = [1, 2, 4]
    l2_num = [3, 6, 9]
    for num in l1_num:
        l1_copy.next = ListNode(num)
        l1_copy = l1_copy.next
    for num in l2_num:
        l2_copy.next = ListNode(num)
        l2_copy = l2_copy.next
    lists = [l1.next, l2.next]
    result = Solution().mergeKLists(lists)
    while result:
        print(result.val)
        result = result.next

執行效率如下:

 

看到這個執行時間之後,說實話,特別受挫,本來覺得特簡單的一題卻整出了個么蛾子,於是我痛定思痛又整出了個執行效率有了極大提高的演算法(其實是借鑑了網上大佬的想法)。這種思想其實我在求合併2個有序連結串列時已經提到啦,當時好像是沒給出具體程式碼,其實是為了這兒買個伏筆,不然就沒新鮮感了嘛!

具體思想:尤其是對於多個有序連結串列來說這種思想尤為適用,可以新建一List陣列,用於存放所有連結串列對應節點的值,然後直接用sort()函式可以直接將陣列中的元素按從小到大的順序排列,這樣可極大地節省連結串列排序的時間(這兒只想說:這方法太牛逼啦),最後只需新建一連結串列把陣列中的值依次賦值給該連結串列即可。

程式碼如下:

class Solution:
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        if len(lists) == 0:
            return []
        L = ListNode(0)
        L_copy = L
        val_lists = []
        for list_index in range(len(lists)):
            single_list = lists[list_index]
            while single_list:
                val_lists.append(single_list.val)
                single_list = single_list.next
        val_lists.sort()
        for index in val_lists:
            L_copy.next = ListNode(index)
            L_copy = L_copy.next
        return L.next


if __name__ == "__main__":
    l1 = ListNode(0)
    l1_copy = l1
    l2 = ListNode(0)
    l2_copy = l2
    l1_num = [1, 2, 4]
    l2_num = [3, 6, 9]
    for num in l1_num:
        l1_copy.next = ListNode(num)
        l1_copy = l1_copy.next
    for num in l2_num:
        l2_copy.next = ListNode(num)
        l2_copy = l2_copy.next
    lists = [l1.next, l2.next]
    result = Solution().mergeKLists(lists)
    while result:
        print(result.val)
        result = result.next

執行效率那是沒話說,基本上都在90%以上,很欣慰了。