Leetcode 23 Merge k Sorted Lists

Leetcode 23 Merge k Sorted Lists

题目描述

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

Example:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路解析
  • 思路一暴力法:将k个链表逐一两两合并,得到结果,代码如下:
# 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:
        k = len(lists)
        if k == 0:
            return None
        if k == 1:
            return lists[0]
        result = self.mergeTwoLists(lists[0], lists[1])
        for i in range(2, k):
            result = self.mergeTwoLists(result, lists[i])
        return result
    def mergeTwoLists(self, l1, l2):
        if l1 is None:
            return l2
        if l2 is None:
            return l1
        result = ListNode(0) # 哑结点
        result_temp = result
        while l1 and l2:
            if l1.val <= l2.val:
                result_temp.next = ListNode(l1.val)
                result_temp = result_temp.next
                l1 = l1.next
            else:
                result_temp.next = ListNode(l2.val)
                result_temp = result_temp.next
                l2 = l2.next
        if l1 is None:
            result_temp.next = l2
        else:
            result_temp.next = l1
        return result.next

但这样做,需要遍历整个列表以及列表中每一个链表的结点,时间复杂度为 O ( l e n ( l i s t s ) ∗ N ) , N 为 结 点 数 之 和 O(len(lists) * N),N为结点数之和 O(len(lists)N)N,不算为一种好的算法

  • 思路二,也是暴力的思路,将所有结点的值存在一个列表里,对列表进行排序,最后生成一个排好序的链表,代码如下:
# 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:
        nodes = []
        for item in lists:
            while item:
                nodes.append(item.val)
                item = item.next
        nodes.sort()
        result = ListNode(0)
        result_temp = result
        for node in nodes:
            result.next = ListNode(node)
            result = result.next            
        return result_temp.next

遍历所有结点的时间复杂度为 O ( N ) O(N) O(N),排序的时间复杂度为 O ( N ∗ l o g N ) O(N*logN) O(NlogN),所以算法的整体时间复杂度为 O ( N ∗ l o g N ) O(N*logN) O(NlogN).(python中sort()函数使用的是Timsort算法,平均时间复杂度为 O ( N ∗ l o g N ) O(N*logN) O(NlogN)

这种思路也可以利用优先队列来实现排序这个操作,得到相同的结果。‘

  • 思路三,分治

分治的算法其实和思路一有些相似,不同的是分治法是两两合并,最后归结为两个长度相差不大的链表合并得到结果。而思路一是逐一两两合并,实现过程并不相同。

注意分治的三条原则:

  1. 原问题可以分解为独立的子问题
  2. 当问题规模小到一定程度,问题可以直接求解
  3. 子问题解的合并即原问题的解
# 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:
        k = len(lists)
        if k == 0:
            return None
        interval = 1
        while interval < k:
            for i in range(0, k - interval, interval * 2):
                lists[i] = self.mergeTwoLists(lists[i], lists[i + interval])
            interval *= 2
        return lists[0]
    
    def mergeTwoLists(self, l1, l2):
        if not l1:
            return l2
        if not l2:
            return l1
        result = ListNode(0)
        result_temp = result
        while l1 and l2:
            if l1.val <= l2.val:
                result_temp.next = ListNode(l1.val)
                result_temp = result_temp.next
                l1 = l1.next
            else:
                result_temp.next = ListNode(l2.val)
                result_temp = result_temp.next
                l2 = l2.next
        if not l1:
            result_temp.next = l2
        else:
            result_temp.next = l1
        return result.next
            

这段代码的关键在于两两合并出的代码,比较巧妙。

整体时间复杂度为 O ( N ∗ l o g 2 k ) O(N*log_2k) O(Nlog2k)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值