To merge k sorted linked lists in O(N log k) time, push the head of each non-empty list into a min-heap keyed by node value. Use tuples (value, uid, node) so Python can compare when values tie. Repeatedly pop the smallest node, append it to the output list, and if that node has a next, push next into the heap. This keeps heap size ≤ k; each of N nodes causes one push/pop → O(N log k).python
import heapq
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def __repr__(self):
return f"{self.val}"
def merge_k_lists(lists):
"""
Merge k sorted linked lists using a heap.
Time: O(N log k), Space: O(k) for heap (plus output list).
"""
heap = []
# Initialize heap with head nodes
for node in lists:
if node:
heapq.heappush(heap, (node.val, id(node), node)) # id() as unique uid
dummy = ListNode(0)
tail = dummy
while heap:
val, _, node = heapq.heappop(heap)
tail.next = node
tail = tail.next
# detach to avoid accidental cycles in some contexts (optional)
next_node = node.next
tail.next = None
if next_node:
heapq.heappush(heap, (next_node.val, id(next_node), next_node))
return dummy.next
# Helper to build and print lists (for testing)
def build_list(arr):
dummy = ListNode(0)
t = dummy
for x in arr:
t.next = ListNode(x)
t = t.next
return dummy.next
def to_list(node):
out = []
while node:
out.append(node.val)
node = node.next
return out
# Example:
lists = [build_list([1,4,5]), build_list([1,3,4]), build_list([2,6])]
merged = merge_k_lists(lists)
print(to_list(merged)) # [1,1,2,3,4,4,5,6]
Key points:- Using (value, uid, node) resolves ties without comparing nodes.- Heap operations are O(log k); each node is pushed/popped once → O(N log k).- Space: O(k) heap plus O(1) extra pointers.Edge cases:- Empty input list, or all lists empty -> return None.- Lists with duplicate values handled by uid.Alternatives:- Divide-and-conquer merge (pairwise) achieving O(N log k) as well; simpler heaps often preferred for streaming.