力扣刷题(python)50天——第十三天:合并K个排序链表

力扣刷题(python)50天——第十三天:合并K个排序链表

题目描述

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

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

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

方法

这道题是上一题的拓展,拿到这题后我没考虑时间复杂度,想法和上一道题一样,依次比较N个节点然后迭代

解答

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

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        lists = list(filter(None, lists))
        l=len(lists)
        if l:
            pass
        else:
            return None
        
        flag=lists[0].val
        l=len(lists)
        rec=0
        for i in range(l):
            if lists[i].val<flag:
                rec=i
                flag=lists[i].val
        l1=lists[rec]
        l2=l1
        lists[rec]=lists[rec].next
        while 1:
            lists = list(filter(None, lists))
            l=len(lists)
            if lists:
                min_v=float('inf')
                for i in range(l):
                    if lists[i].val<min_v:
                        min_v=lists[i].val
                        rec=i
                l1.next=lists[rec]
                lists[rec]=lists[rec].next
                l1=l1.next
            else:
                break
        return l2

值得注意的是对于python,如果想去除列表中所有的None,最好用filter方法,或者用另一个空列表进行检测添加。

执行结果

执行结果:通过
执行用时 :6548 ms, 在所有 Python 提交中击败了5.01%的用户
内存消耗 :17.3 MB, 在所有 Python 提交中击败了55.61%的用户
在这里插入图片描述
.。。。。。。。这成绩意料之中,因为之前用

for i in range(l):
	for each in lists:
		if each is None:
			lists.remove(each)

来去除None,耗费大量时间
所以一直超时,但也说明算法本身也有问题

在未改良的基础上,N个节点一共需要N个循环确定,每次循环都要遍历K个链表,并进行迭代操作,所以时间复杂度为O(NK),非常高。

参考改进:

1.使用暴力法

将所有链表进行一次遍历,放在数组中进行排序:
暴力法都比我强!!!!!!!!!!!!!!!QQA

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        self.nodes = []
        head = point = ListNode(0)
        for l in lists:
            while l:
                self.nodes.append(l.val)
                l = l.next
        for x in sorted(self.nodes):
            point.next = ListNode(x)
            point = point.next
        return head.next

作者:LeetCode
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/he-bing-kge-pai-xu-lian-biao-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时间复杂度:O(N\log N) ,其中 N 是节点的总数目。
遍历所有的值需花费 O(N) 的时间。
一个稳定的排序算法花费 O(N\log N) 的时间。
遍历同时创建新的有序链表花费 O(N) 的时间。

2.分治:

将k个链表逐个两两配对为一组
在这里插入图片描述
该过程会有logk次,每次遍历N个节点,时间复杂度O(N log K)

class Solution(object):
    def mergeKLists(self, lists):
        """
        :type lists: List[ListNode]
        :rtype: ListNode
        """
        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

作者:LeetCode
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/he-bing-kge-pai-xu-lian-biao-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

心得:

不是搞得特别通时间复杂度是怎么算的,总感觉很别扭。对于为什么分治会时间上短那么多,我的理解是分治后会相当于进行一次排序,就简化了一些,也不是很懂。

摘自百度百科:
采用分治法解决的问题一般具有的特征如下:

  1. 问题的规模缩小到一定的规模就可以较容易地解决。
  2. 问题可以分解为若干个规模较小的模式相同的子问题,即该问题具有最优子结构性质。
  3. 合并问题分解出的子问题的解可以得到问题的解。
  4. 问题所分解出的各个子问题之间是独立的,即子问题之间不存在公共的子问题。

看了后现在觉得,既然上一题是两个链表合并,那么这道题不就能分治成很多两个链表合并的子问题了吗。加深了理解什么是分治。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值