Merge k Sorted Lists in Python

Merging k sorted lists is a classic algorithm problem. Given multiple sorted linked lists, we need to combine them into a single sorted list. Python's heapq module provides an efficient solution using a min-heap data structure.

Problem Understanding

Given k sorted linked lists like [1,4,5], [1,3,4], [2,6], we need to merge them into one sorted list [1,1,2,3,4,4,5,6].

Algorithm Steps

  • Create a min-heap to store the smallest elements from each list

  • Add the first node of each non-empty list to the heap

  • Repeatedly extract the minimum element from the heap

  • Add the next node from the same list (if exists) back to the heap

  • Continue until the heap is empty

Using Python's heapq Module

import heapq

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
    
    def __lt__(self, other):
        return self.val < other.val

def merge_k_lists(lists):
    heap = []
    
    # Add first node of each non-empty list to heap
    for i, node in enumerate(lists):
        if node:
            heapq.heappush(heap, node)
    
    dummy = ListNode(0)
    current = dummy
    
    while heap:
        # Extract minimum node
        min_node = heapq.heappop(heap)
        current.next = min_node
        current = current.next
        
        # Add next node from same list to heap
        if min_node.next:
            heapq.heappush(heap, min_node.next)
    
    return dummy.next

# Helper function to create linked list from array
def create_list(arr):
    if not arr:
        return None
    head = ListNode(arr[0])
    current = head
    for val in arr[1:]:
        current.next = ListNode(val)
        current = current.next
    return head

# Helper function to print linked list
def print_list(head):
    result = []
    while head:
        result.append(head.val)
        head = head.next
    return result

# Example usage
lists_data = [[1,4,5], [1,3,4], [2,6]]
linked_lists = [create_list(arr) for arr in lists_data]
merged = merge_k_lists(linked_lists)
print(print_list(merged))
[1, 1, 2, 3, 4, 4, 5, 6]

Alternative Approach: Divide and Conquer

def merge_two_lists(l1, l2):
    dummy = ListNode(0)
    current = dummy
    
    while l1 and l2:
        if l1.val <= l2.val:
            current.next = l1
            l1 = l1.next
        else:
            current.next = l2
            l2 = l2.next
        current = current.next
    
    current.next = l1 or l2
    return dummy.next

def merge_k_lists_divide_conquer(lists):
    if not lists:
        return None
    
    while len(lists) > 1:
        merged_lists = []
        
        # Merge lists in pairs
        for i in range(0, len(lists), 2):
            l1 = lists[i]
            l2 = lists[i + 1] if i + 1 < len(lists) else None
            merged_lists.append(merge_two_lists(l1, l2))
        
        lists = merged_lists
    
    return lists[0]

# Example usage
lists_data = [[1,4,5], [1,3,4], [2,6]]
linked_lists = [create_list(arr) for arr in lists_data]
merged = merge_k_lists_divide_conquer(linked_lists)
print(print_list(merged))
[1, 1, 2, 3, 4, 4, 5, 6]

Time Complexity Comparison

Approach Time Complexity Space Complexity
Min-Heap O(n log k) O(k)
Divide & Conquer O(n log k) O(1)

Where n is the total number of nodes and k is the number of lists.

Conclusion

Both approaches efficiently merge k sorted lists with O(n log k) time complexity. The heap approach is intuitive and easy to implement, while divide-and-conquer uses less extra space. Choose based on your specific requirements and constraints.

Updated on: 2026-03-25T08:37:00+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements