Merge K Sorted Linked Lists using Min Heap (original) (raw)
Last Updated : 3 Oct, 2025
Given **k sorted linked lists of different sizes, we need to **merge them all maintaining their **sorted order.
**Examples:
**Input: k = 3, n = 4
list1 = 1->3->5->7->NULL
list2 = 2->4->6->8->NULL
list3 = 0->9->10->11->NULL
**Output: 0->1->2->3->4->5->6->7->8->9->10->11
**Explanation: Merged lists in a sorted order where every element is greater than the previous element.**Input: k = 3, n = 3
list1 = 1->3->7->NULL
list2 = 2->4->8->NULL
list3 = 9->10->11->NULL
**Output: 1->2->3->4->7->8->9->10->11
**Explanation: Merged lists in a sorted order where every element is greater than the previous element.
We have discussed different solutions to Merge K sorted Lists. In this post, we are going to focus on Min Heap or Priority Queue based solution which is acceptable for this problem.
**Approach:
The idea is to use a min heap to efficiently track the **smallest element among all lists at any given time by initially storing the first node from each list in the heap, then repeatedly extracting the minimum element to build the merged list while adding the **next node from that same list to maintain the heap's role in finding the next smallest element.
C++ `
#include #include #include using namespace std;
class Node { public: int data; Node* next; Node(int x) { data = x; next = nullptr; } };
// Custom class for min heap class Compare { public: bool operator()(Node* a, Node* b) { return a->data > b->data; } };
// Function to merge K sorted linked lists Node* mergeKLists(vector<Node*>& arr) {
priority_queue<Node*, vector<Node*>, Compare> pq;
// Insert the head nodes of k lists
for (Node* head: arr) {
if (head != nullptr) pq.push(head);
}
// Initialize a dummy head
Node* dummy = new Node(-1);
Node* tail = dummy;
while (!pq.empty()) {
// Pop the min node
Node* top = pq.top();
pq.pop();
// Append the node into list
tail->next = top;
tail = top;
// If top node has next node,
// add it to the heap.
if (top->next!=nullptr) {
pq.push(top->next);
}
}
return dummy->next;}
void printList(Node* node) { while (node != nullptr) { cout << node->data; if(node->next) cout << "->"; node = node->next; } }
int main() { int k = 3;
vector<Node*> arr(k);
arr[0] = new Node(1);
arr[0]->next = new Node(3);
arr[0]->next->next = new Node(5);
arr[0]->next->next->next = new Node(7);
arr[1] = new Node(2);
arr[1]->next = new Node(4);
arr[1]->next->next = new Node(6);
arr[1]->next->next->next = new Node(8);
arr[2] = new Node(0);
arr[2]->next = new Node(9);
arr[2]->next->next = new Node(10);
arr[2]->next->next->next = new Node(11);
Node* head = mergeKLists(arr);
printList(head);
return 0;}
Java
import java.util.List; import java.util.ArrayList; import java.util.PriorityQueue;
class Node { int data; Node next;
Node(int x) {
data = x;
next = null;
}}
class GfG {
// Function to merge K sorted linked lists
static Node mergeKLists(List<Node> arr) {
PriorityQueue<Node> pq = new PriorityQueue<>((a, b) -> a.data - b.data);
// Insert the head nodes of k lists
for (Node head : arr) {
if (head != null) pq.add(head);
}
// Initialize a dummy head
Node dummy = new Node(-1);
Node tail = dummy;
while (!pq.isEmpty()) {
// Pop the min node
Node top = pq.poll();
// Append the node into list
tail.next = top;
tail = top;
// If top node has next node,
// add it to the heap.
if (top.next != null) {
pq.add(top.next);
}
}
return dummy.next;
}
static void printList(Node node) {
while (node != null) {
System.out.print(node.data);
if(node.next != null){
System.out.print("->");
}
node = node.next;
}
}
public static void main(String[] args) {
int k = 3;
List<Node> arr = new ArrayList<>();
arr.add(new Node(1));
arr.get(0).next = new Node(3);
arr.get(0).next.next = new Node(5);
arr.get(0).next.next.next = new Node(7);
arr.add(new Node(2));
arr.get(1).next = new Node(4);
arr.get(1).next.next = new Node(6);
arr.get(1).next.next.next = new Node(8);
arr.add(new Node(0));
arr.get(2).next = new Node(9);
arr.get(2).next.next = new Node(10);
arr.get(2).next.next.next = new Node(11);
Node head = mergeKLists(arr);
printList(head);
}}
Python
import heapq
class Node: def init(self, x): self.data = x self.next = None
Function to merge K sorted linked lists
def mergeKLists(arr): pq = []
# Insert the head nodes of k lists
for i in range(0, len(arr)):
head = arr[i]
if head is not None:
heapq.heappush(pq, (head.data, i, head))
# Initialize a dummy head
dummy = Node(-1)
tail = dummy
while pq:
# Pop the min node
_, index, top = heapq.heappop(pq)
# Append the node into list
tail.next = top
tail = top
# If top node has next node,
# add it to the heap.
if top.next is not None:
heapq.heappush(pq, (top.next.data, index, top.next))
return dummy.nextdef printList(node): while node is not None: print(node.data, end="") if node.next is not None: print("->", end="") node = node.next print()
if name == "main": k = 3
arr = [None] * k
arr[0] = Node(1)
arr[0].next = Node(3)
arr[0].next.next = Node(5)
arr[0].next.next.next = Node(7)
arr[1] = Node(2)
arr[1].next = Node(4)
arr[1].next.next = Node(6)
arr[1].next.next.next = Node(8)
arr[2] = Node(0)
arr[2].next = Node(9)
arr[2].next.next = Node(10)
arr[2].next.next.next = Node(11)
head = mergeKLists(arr)
printList(head)C#
using System; using System.Collections.Generic;
class Node { public int data; public Node next;
public Node(int x) {
data = x;
next = null;
}}
// Custom comparator class for min heap class NodeComparer : IComparer { public int Compare(Node a, Node b) { if (a.data > b.data) return 1; else if (a.data < b.data) return -1; return 0; } }
class GfG {
// Function to merge K sorted linked lists
static Node mergeKLists(List<Node> arr) {
PriorityQueue<Node> pq = new PriorityQueue<Node>(new NodeComparer());
// Insert the head nodes of k lists
foreach (Node head in arr) {
if (head != null) pq.Enqueue(head);
}
Node dummy = new Node(-1);
Node tail = dummy;
while (pq.Count > 0) {
// Pop the min node
Node top = pq.Dequeue();
// Append the node into list
tail.next = top;
tail = top;
// If top node has next node,
// add it to the heap.
if (top.next != null) {
pq.Enqueue(top.next);
}
}
return dummy.next;
}
static void printList(Node node) {
while (node != null) {
Console.Write(node.data);
if(node.next != null){
Console.Write("->");
}
node = node.next;
}
}
static void Main(string[] args) {
List<Node> arr = new List<Node>();
arr.Add(new Node(1));
arr[0].next = new Node(3);
arr[0].next.next = new Node(5);
arr[0].next.next.next = new Node(7);
arr.Add(new Node(2));
arr[1].next = new Node(4);
arr[1].next.next = new Node(6);
arr[1].next.next.next = new Node(8);
arr.Add(new Node(0));
arr[2].next = new Node(9);
arr[2].next.next = new Node(10);
arr[2].next.next.next = new Node(11);
Node head = mergeKLists(arr);
printList(head);
}}
// Custom Priority queue class PriorityQueue { private List heap; private IComparer comparer;
public PriorityQueue(IComparer<T> comparer = null) {
this.heap = new List<T>();
this.comparer = comparer ?? Comparer<T>.Default;
}
public int Count => heap.Count;
// Enqueue operation
public void Enqueue(T item) {
heap.Add(item);
int i = heap.Count - 1;
while (i > 0) {
int parent = (i - 1) / 2;
if (comparer.Compare(heap[parent], heap[i]) <= 0)
break;
Swap(parent, i);
i = parent;
}
}
// Dequeue operation
public T Dequeue() {
if (heap.Count == 0)
throw new InvalidOperationException("Priority queue is empty.");
T result = heap[0];
int last = heap.Count - 1;
heap[0] = heap[last];
heap.RemoveAt(last);
last--;
int i = 0;
while (true) {
int left = 2 * i + 1;
if (left > last)
break;
int right = left + 1;
int minChild = left;
if (right <= last && comparer.Compare(heap[right], heap[left]) < 0)
minChild = right;
if (comparer.Compare(heap[i], heap[minChild]) <= 0)
break;
Swap(i, minChild);
i = minChild;
}
return result;
}
// Swap two elements in the heap
private void Swap(int i, int j) {
T temp = heap[i];
heap[i] = heap[j];
heap[j] = temp;
}}
JavaScript
class Node { constructor(x) { this.data = x; this.next = null; } }
// Comparator function to compare Node data function nodeComparator(k1, k2) { if (k1.data > k2.data) return -1; if (k1.data < k2.data) return 1; return 0; }
class PriorityQueue { constructor(compare) { this.heap = []; this.compare = compare; }
enqueue(value) { this.heap.push(value); this.bubbleUp(); }
bubbleUp() { let index = this.heap.length - 1; while (index > 0) { let element = this.heap[index], parentIndex = Math.floor((index - 1) / 2), parent = this.heap[parentIndex]; if (this.compare(element, parent) < 0) break; this.heap[index] = parent; this.heap[parentIndex] = element; index = parentIndex; } }
dequeue() { let max = this.heap[0]; let end = this.heap.pop(); if (this.heap.length > 0) { this.heap[0] = end; this.sinkDown(0); } return max; }
sinkDown(index) { let left = 2 * index + 1, right = 2 * index + 2, largest = index;
if (
left < this.heap.length &&
this.compare(this.heap[left], this.heap[largest]) > 0
) {
largest = left;
}
if (
right < this.heap.length &&
this.compare(this.heap[right], this.heap[largest]) > 0
) {
largest = right;
}
if (largest !== index) {
[this.heap[largest], this.heap[index]] = [
this.heap[index],
this.heap[largest],
];
this.sinkDown(largest);
}}
isEmpty() { return this.heap.length === 0; } }
// Function to merge K sorted linked lists function mergeKLists(arr) { const pq = new PriorityQueue(nodeComparator);
// Insert the head nodes of k lists
for (let head of arr) {
if (head !== null) pq.enqueue(head);
}
let dummy = new Node(-1);
let tail = dummy;
while (!pq.isEmpty()) {
// Pop the min node
let top = pq.dequeue();
// Append the node into list
tail.next = top;
tail = top;
// If top node has next node,
// add it to the heap.
if (top.next !== null) {
pq.enqueue(top.next);
}
}
return dummy.next;}
function printList(node) { while (node !== null) { process.stdout.write(node.data.toString()); if (node.next !== null) { process.stdout.write("->"); } node = node.next; } console.log(); }
let k = 3;
let arr = [];
arr[0] = new Node(1); arr[0].next = new Node(3); arr[0].next.next = new Node(5); arr[0].next.next.next = new Node(7);
arr[1] = new Node(2); arr[1].next = new Node(4); arr[1].next.next = new Node(6); arr[1].next.next.next = new Node(8);
arr[2] = new Node(0); arr[2].next = new Node(9); arr[2].next.next = new Node(10); arr[2].next.next.next = new Node(11);
let head = mergeKLists(arr);
printList(head);
`
Output
0->1->2->3->4->5->6->7->8->9->10->11
**Time Complexity: O(n * log k) , where n is the total sum of nodes from all lists.
**Auxiliary Space: O(k), due to heap. There are at most k elements at any instant.