赞
踩
本文为Python算法题集之一的代码示例
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i]
按 升序 排列lists[i].length
的总和不超过 10^4
通常优化:减少循环层次
通常优化:增加分支,减少计算集
通常优化:采用内置算法来提升计算速度
分析题目特点,分析最优解
可以考虑采用堆结构来进行排序
可以采用分治法对多链表进行两两合并,化整为零,递归处理
可以用列表排序法进行简单排序
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块外层循环,内层最小值检测,依次将最小节点连接起来,性能自然不是最求目标
勉强通关,超过07%
import CheckFuncPerf as cfp class Solution: @staticmethod def mergeKLists_base(lists): ilen = len(lists) if ilen < 1: return None res_head = ListNode(0) tmpNode = res_head blast = True while blast: blast, bNone = False, True for iIdx in range(ilen): if lists[iIdx]: if bNone: minVal, minidx, bNone = lists[iIdx].val, iIdx, False else: if lists[iIdx].val < minVal: minVal, minidx, bNone = lists[iIdx].val, iIdx, False if not bNone: blast = True tmpNode.next = lists[minidx] lists[minidx] = lists[minidx].next tmpNode = tmpNode.next return res_head.next result = cfp.getTimeMemoryStr(Solution.mergeKLists_base, alists) print(result['msg'], '执行结果 = {}'.format(result['result'].val)) # 运行结果 函数 mergeKLists_base 的运行时间为 950.22 ms;内存使用量为 4.00 KB 执行结果 = 0
将所有节点均存入列表结构,通过列表排序,最后再连接起来,代码简洁,性能优异,但是内存O(n)
性能卓越,超越96%
import CheckFuncPerf as cfp class Solution: @staticmethod def mergeKLists_ext1(lists): ilen = len(lists) if ilen < 1: return None list_node = [] for iIdx in range(ilen): while lists[iIdx]: list_node.append([lists[iIdx].val, lists[iIdx]]) lists[iIdx] = lists[iIdx].next sort_list = sorted(list_node, key=lambda x: x[0]) for iIdx in range(len(sort_list)-1): sort_list[iIdx][1].next = sort_list[iIdx+1][1] sort_list[-1][1].next = None return sort_list[0][1] result = cfp.getTimeMemoryStr(Solution.mergeKLists_ext1, alists) print(result['msg'], '执行结果 = {}'.format(result['result'].val)) # 运行结果 函数 mergeKLists_ext1 的运行时间为 913.20 ms;内存使用量为 992.00 KB 执行结果 = 0
应用堆队列heapq
来进行最小值检测,代码相对简洁,性能还行
马马虎虎,超过72%
import CheckFuncPerf as cfp class Solution: @staticmethod def mergeKLists_ext2(lists): import heapq res_head = ListNode(0) tmpNode = res_head buffmin = [] for iIdx in range(len(lists)): if lists[iIdx] : heapq.heappush(buffmin, (lists[iIdx].val, iIdx)) lists[iIdx] = lists[iIdx].next while buffmin: minval, minidx = heapq.heappop(buffmin) tmpNode.next = ListNode(minval) tmpNode = tmpNode.next if lists[minidx]: heapq.heappush(buffmin, (lists[minidx].val, minidx)) lists[minidx] = lists[minidx].next return res_head.next result = cfp.getTimeMemoryStr(Solution.mergeKLists_ext1, alists) print(result['msg'], '执行结果 = {}'.format(result['result'].val)) # 运行结果 函数 mergeKLists_ext2 的运行时间为 958.21 ms;内存使用量为 4.00 KB 执行结果 = 0
使用递归设计,每次合并两个链表,直到最后合成总链表;这种方式类似分区海选,不是每个选手都要面对所有人,效率最高,资源最少
性能卓越,超越95%
import CheckFuncPerf as cfp class Solution: @staticmethod def mergeKLists_ext3(lists): def mergeTwoLists(link1, link2) -> ListNode: res_head = ListNode(0) tmpNode = res_head while link1 and link2: if link1.val < link2.val: tmpNode.next = link1 link1 = link1.next else: tmpNode.next = link2 link2 = link2.next tmpNode = tmpNode.next tmpNode.next = link1 if link1 else link2 return res_head.next def mergeSort(lists, left, right) -> ListNode: if left == right: return lists[left] mid = (left + right) // 2 leftlink = mergeSort(lists, left, mid) rightlink = mergeSort(lists, mid + 1, right) return mergeTwoLists(leftlink, rightlink) ilen = len(lists) if ilen < 1: return None return mergeSort(lists, 0, ilen - 1) result = cfp.getTimeMemoryStr(Solution.mergeKLists_ext3, alists) print(result['msg'], '执行结果 = {}'.format(result['result'].val)) # 运行结果 函数 mergeKLists_ext3 的运行时间为 393.49 ms;内存使用量为 0.00 KB 执行结果 = 0
根据本地日志分析,最优算法为第4种mergeKLists_ext3
def generateOneLinkedList(data): head = ListNode() current_node = head for num in data: new_node = ListNode(num) current_node.next = new_node current_node = new_node return head.next def generateOneLinks(listlink): result = [] for iIdx in range(len(listlink)): result.append(generateOneLinkedList(listlink[iIdx])) return result iLen, k = 100000, 10 listnums = [] for iIdx in range(k): tmpNums = [x*(iIdx+1) for x in range(iLen)] listnums.append(tmpNums) alists = generateOneLinks(listnums) result = cfp.getTimeMemoryStr(Solution.mergeKLists_base, alists) print(result['msg'], '执行结果 = {}'.format(result['result'].val)) # 算法本地速度实测比较 函数 mergeKLists_base 的运行时间为 950.22 ms;内存使用量为 4.00 KB 执行结果 = 0 函数 mergeKLists_ext1 的运行时间为 913.20 ms;内存使用量为 992.00 KB 执行结果 = 0 函数 mergeKLists_ext2 的运行时间为 958.21 ms;内存使用量为 4.00 KB 执行结果 = 0 函数 mergeKLists_ext3 的运行时间为 393.49 ms;内存使用量为 0.00 KB 执行结果 = 0
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。