【Leetcode 23】合并K个排序链表

题目描述

在这里插入图片描述

解题思路

解法一:暴力法

  • 遍历k个链表,将所有节点值保存到列表中
  • 将列表排序
  • 遍历排序后的列表,创建一个新的有序链表

python代码

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

class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        self.nodes = []
        tmp = head = ListNode(0)
        for i in lists:
            while i:
                self.nodes.append(i.val)
                i = i.next
        for j in sorted(self.nodes):
            head.next = ListNode(j)
            head = head.next
        return tmp.next

运行结果

时间复杂度O(NlogN)O(NlogN),其中 NN是节点的总数目。

  • 遍历所有的值需花费 O(N)O(N)的时间。
  • 一个稳定的排序算法花费 O(NlogN)O(Nlog N) 的时间。
  • 遍历同时创建新的有序链表花费 O(N)O(N)的时间。

空间复杂度O(N)O(N)

  • 排序花费 O(N)O(N)空间(这取决于你选择的算法)。
  • 创建一个新的链表花费 O(N)O(N) 的空间。
    在这里插入图片描述

解法二:分治算法

分治其实就是不断缩小其规模,再不断合并扩大的过程
在这里插入图片描述
找到中间点,将其一分为二,再不停的进行拆分,直至到不能再拆分(规模为1的时候)便返回。
之后开始合并,合并的代码借用了合并两个排序链表的代码。
当两个规模最小的链表合并完后,其规模就变大了,然后不断重复这个合并过程,直到最终得到一个有序的链表。

python代码

 amount = len(lists)
        interval = 1
        while interval < amount:
            for i in range(0, amount - interval, interval * 2):
                lists[i] = self.merge2Lists(lists[i], lists[i + interval])
            interval *= 2
        return lists[0] if amount > 0 else lists

    def merge2Lists(self, l1, l2):
        head = point = ListNode(0)
        while l1 and l2:
            if l1.val <= l2.val:
                point.next = l1
                l1 = l1.next
            else:
                point.next = l2
                l2 = l1
                l1 = point.next.next
            point = point.next
        if not l1:
            point.next=l2
        else:
            point.next=l1
        return head.next 

运行结果

时间复杂度O(Nlogk)O(N\log k) ,其中k是链表的数目。

  • 我们可以在O(n)O(n)的时间内合并两个有序链表,其中 n是两个链表中的总节点数。
  • 将所有的合并进程加起来,我们可以得到:在这里插入图片描述

空间复杂度:O(1).
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章