合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6 用时最短
class Solution: def mergeKLists(self, lists: List[ListNode]) -> ListNode: dummy = pre = ListNode(-1) nums = [] for node in lists: while node: nums.append(node) node = node.next for node in sorted(nums,key=lambda n:n.val): pre.next = node pre = pre.next return dummy.next最小堆
from heapq import heapify, heappop class Solution: def mergeKLists(self, lists: List[ListNode]) -> ListNode: # 读取所有的节点值 h = [] for node in lists: while node: h.append(node.val) node = node.next # 构造一个最小堆 if not h: return None heapify(h) # 转换成最小堆 # 构造链表 root = ListNode(heappop(h)) curnode = root while h: nextnode = ListNode(heappop(h)) curnode.next = nextnode curnode = nextnode return root分治解法
class Solution: def mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode: l = ListNode(0) temp = l while l1 or l2: if not l1: temp.next = l2 break elif not l2: temp.next = l1 break v1 = l1.val v2 = l2.val if l1.val < v2 : temp.next = ListNode(v1) l1 = l1.next else: temp.next = ListNode(v2) l2 = l2.next temp = temp.next return l.next def mergeKLists(self, lists: List[ListNode]) -> ListNode: lens = len(lists) if not lens: return None elif lens == 1: return lists[0] elif lens ==2: return Solution.mergeTwoLists(lists[0],lists[1]) mid = lens//2 l1 = [] l2 = [] for i in range(mid): l1.append(lists[i]) for i in range(mid,lens): l2.append(lists[i]) return Solution.mergeTwoLists(self.mergeKLists(l1),self.mergeKLists(l2))普通解法
class Solution: def mergeKLists(self, listss: List[ListNode]) -> ListNode: l = ListNode(0) temp = l lists = [] for node in listss: if node : lists.append(node) while lists: minval = lists[0].val index = 0 # minval = 8 for i in range(len(lists)): if lists[i].val < minval: minval, index = lists[i].val, i print('min:',minval, 'index:',index) temp.next = ListNode(minval) lists[index] = lists[index].next if not lists[index]: lists.remove(lists[index]) print('remove:',index) temp = temp.next return l.nextlambda相关
lambda作为一个表达式,定义了一个隐函数,上例的代码n为入口参数,n.val为函数体
最小堆相关
最小堆是一棵完全二叉树,非叶子结点的值不大于左孩子和右孩子的值。
分治相关
分治法得基本步骤: step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
step3 合并:将各个子问题的解合并为原问题的解。
它的一般的算法设计模式如下: Divide-and-Conquer(P ) 1. if |P|≤n0 2. then return(ADHOC(P )) 3. 将P分解为较小的子问题 P1 ,P2 ,…,Pk 4. for i←1 to k 5. do yi ← Divide-and-Conquer(Pi) △ 递归解决Pi 6. T ← MERGE(y1,y2,…,yk) △ 合并子问题 7. return(T)
其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC (p )是该分治法中的基本子算法,用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(p )求解。算法MERGE(y1,y2,…,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,…,Pk的相应的解y1,y2,…,yk合并为P的解。