标签:最大堆 class 合并 两种方法 node 用例 报错 节点 log
题目:
合并k个有序链表,并将结果用一个有序链表输出
例如:
输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6
思路:
假设k个链表的总元素数目为n。首先想到两两合并列表,在序列1和2合并,3和4合并,依次类推。直到合并的只剩一个链表。这种操作的时间复杂度为O(nlog(k)),空间复杂度为O(1)。python代码如下:
class Solution(object): def mergeKLists(self, lists): if not lists: return None while len(lists) > 1: tmp_node = self.mergeTwoLists(lists.pop(0), lists.pop(0)) lists.append(tmp_node) return lists[0] def mergeTwoLists(self, p1, p2): new_head = ListNode(-1) tail = new_head while p1 is not None and p2 is not None: if p1.val <= p2.val: tail.next, tail = p1, p1 p1 = p1.next else: tail.next, tail = p2, p2 p2 = p2.next if p1 is None: tail.next = p2 elif p2 is None: tail.next = p1 return new_head.next
注意到在mergeTwoLists()中使用了循环进行合并。当节点数量n大于1000时,使用循环合并比较有效。因为python默认限制函数迭代次数为1000,用迭代的方法合并两个链表,节点数多了就会报错。
还可以同时合并所有列表,这中间需要比较这k个链表的头结点哪个最小。直接比较效率低,想到构建辅助数组,用最大堆来帮助比较。这样做的时间复杂度也是O(nlog(k)),空间复杂度为O(k)。同时注意到某些链表合并完后,辅助数组的长度减小,单次查找速度复杂度会小于log(k)。因此这种用最小堆合并的方式速度会比二分合并快一些。实际上在LeetCode23. Merge k Sorted Lists的测试用例上跑的时候,两种方法花的时间分别是165ms,103ms。
import heapq class Solution(object): def mergeKLists(self, lists): head = ListNode(-1) current = head heap = [] for node in lists: if node: heap.append((node.val, node)) heapq.heapify(heap) while heap: _, ref = heapq.heappop(heap) current.next = ref current = current.next if ref.next: heapq.heappush(heap, (ref.next.val, ref.next)) return head.next
标签:最大堆 class 合并 两种方法 node 用例 报错 节点 log
原文地址:https://www.cnblogs.com/plank/p/9144288.html