To improve upon Saurabh's answer, you can generate the final sorted list while iterating over the individual lists.
The idea is to first populate the heap with the first element of each sorted array tagged with the array the element came from, and whenever popping from the heap, add the next element of the array associated with the element just popped from the heap.
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
heap = []
for i, l in enumerate(lists):
if l is None:
continue
heapq.heappush(heap, (l.val,i))
lists[i] = lists[i].next
out = ListNode() # dummy
cur = out
while heap:
val, i = heapq.heappop(heap)
cur.next = ListNode(val)
cur = cur.next
if lists[i] is not None:
heapq.heappush(heap, (lists[i].val, i))
lists[i] = lists[i].next
return out.next
This can also be modified so that the heap keeps track of the actual nodes so that no new nodes (besides the dummy head) are created:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
heap = []
for i, l in enumerate(lists):
if l is None:
continue
heapq.heappush(heap, (l.val, i, l))
lists[i] = lists[i].next
out = ListNode() # dummy
cur = out
while heap:
val, i, node = heapq.heappop(heap)
cur.next = node
cur = cur.next
if lists[i] is not None:
heapq.heappush(heap, (lists[i].val, i, lists[i]))
lists[i] = lists[i].next
return out.next
The heap will only ever contain a maximum k
elements where k
is the number of input lists. Thus, we address @Abhishek Jaiswal's concern that the space complexity should be O(k)
.
Edit: add space complexity improvement analysis