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:链接
使用堆这一数据结构,首先将每条链表的头节点进入堆中,然后将最小的弹出,并将最小的节点这条链表的下一个节点入堆,依次类推,最终形成的链表就是归并好的链表。
heapq使用说明:
a为普通列表
- heapq.heapify(a) 调整a,使得其满足最小堆
- heapq.heappop(a) 从最小堆中弹出最小的元素 ,弹出仍然是一个最小堆
- heapq.heappush(a,b) 向最小堆中压入新的元素,压入仍然是一个最小堆
如果传进元组,第一个元素必须是要比较的值!
# 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
"""
# 定义一个最小堆
heap = []
for l in lists:
# 必须判断是否为空
if l:
heap.append((l.val, l))
# 调整heap使之成为一个最小堆
heapq.heapify(heap)
head = ListNode(0)
dummy = head
while heap:
# 弹出最小元素
_, cur = heapq.heappop(heap)
dummy.next = cur
dummy = dummy.next
# 向最小堆中压入新的元素
if cur.next:
heapq.heappush(heap, (cur.next.val, cur.next))
return head.next
自己实现堆的结构,修改了好多次,终于a过去了。需要注意的是:
1)堆保存的是(结点值,结点)的元组,但是进行HeadAdjust的时候,比较的是第一个元素结点值,而调整的是第二个元素结点。
2)如果选出的最小结点有next,就插入到最小堆的0位置;如果选出的最小结点没有next,仍然得进行堆调整,此时就是把堆的最后一个元素插入到0位置。但是必须此时堆中的元素个数要大于1。
3)使用pop和insert的方法对堆进行调整,直接赋值会TLE。
4)如果每次都用建堆的方法调整,肯定可以,但是会TLE。
# 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
"""
heap = []
for l in lists:
# 必须不为空才能加入heap中
if l:
heap.append((l.val, l))
length = len(heap)
for i in range(0, length//2)[::-1]:
self.HeadAdjust(heap, i, length)
head = ListNode(0)
dummy = head
while heap:
_, cur = heap.pop(0)
dummy.next = cur
dummy = dummy.next
if cur.next:
heap.insert(0, (cur.next.val, cur.next))
self.HeadAdjust(heap, 0, len(heap))
else:
if len(heap) >= 1:
heap.insert(0, heap.pop())
self.HeadAdjust(heap, 0, len(heap))
return head.next
def HeadAdjust(self, input_list, parent, length):
cur = input_list[parent]
temp = input_list[parent][0]
child = 2 * parent + 1
while child < length:
if child + 1 < length and input_list[child+1][0] < input_list[child][0]:
child += 1
if temp <= input_list[child][0]:
break
input_list[parent] = input_list[child]
parent = child
child = 2 * parent + 1
input_list[parent] = cur
return input_list