Merge K Sorted Lists Using Min Heap in DSA Javascript - Time & Space Complexity
When merging multiple sorted lists, we want to know how the time needed grows as the number of lists and their sizes increase.
We ask: How does the merging time change when we have more lists or longer lists?
Analyze the time complexity of the following code snippet.
function mergeKLists(lists) {
const minHeap = new MinHeap();
for (const list of lists) {
if (list) minHeap.insert(list);
}
const dummy = new ListNode(0);
let current = dummy;
while (!minHeap.isEmpty()) {
const node = minHeap.extractMin();
current.next = node;
current = current.next;
if (node.next) minHeap.insert(node.next);
}
return dummy.next;
}
This code merges k sorted linked lists by always picking the smallest current node using a min heap.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Extracting the smallest node from the min heap and inserting the next node from that list.
- How many times: This happens once for every node across all lists, so total nodes n times.
Each node is inserted and extracted from the heap, which takes time depending on the number of lists k.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 nodes, 3 lists | About 10 insertions and 10 extractions, each costing log 3 steps |
| 100 nodes, 5 lists | About 100 insertions and 100 extractions, each costing log 5 steps |
| 1000 nodes, 10 lists | About 1000 insertions and 1000 extractions, each costing log 10 steps |
Pattern observation: The total work grows roughly with the total number of nodes times the log of the number of lists.
Time Complexity: O(n log k)
This means the time grows with the total number of nodes n multiplied by the logarithm of the number of lists k.
[X] Wrong: "Merging k lists is just like merging two lists, so it takes O(n) time."
[OK] Correct: Merging k lists involves repeatedly choosing the smallest among k current nodes, which costs extra time. The heap helps manage this efficiently, but the log k factor matters.
Understanding this complexity shows you can handle multiple sorted inputs efficiently, a common real-world task when combining data streams or search results.
"What if we used a simple array instead of a min heap to find the smallest node each time? How would the time complexity change?"
Practice
K sorted lists?Solution
Step 1: Understand the role of min heap in merging
A min heap helps quickly find the smallest element among multiple candidates, which is essential when merging sorted lists.Step 2: Apply this to merging K sorted lists
By pushing the first element of each list into the min heap, we can always extract the smallest element efficiently to build the merged list.Final Answer:
To efficiently find the smallest element among the heads of all lists -> Option BQuick Check:
Min heap = smallest element finder [OK]
- Thinking min heap sorts entire lists
- Assuming min heap stores all elements at once
- Confusing min heap with max heap
Solution
Step 1: Understand insertion in min heap
To insert, add the element at the end (push), then move it up to maintain heap property (heapifyUp).Step 2: Match with options
heap.push(element); heapifyUp(); correctly shows push followed by heapifyUp, which is the standard insertion method.Final Answer:
heap.push(element); heapifyUp(); -> Option AQuick Check:
Insert = push + heapifyUp [OK]
- Using pop or shift to insert
- Calling heapifyDown after insertion
- Using unshift which is inefficient
const lists = [[1,4,5],[1,3,4],[2,6]];
function mergeKLists(lists) {
const minHeap = [];
const result = [];
for (let i = 0; i < lists.length; i++) {
if (lists[i].length > 0) minHeap.push({ val: lists[i][0], listIndex: i, elementIndex: 0 });
}
minHeap.sort((a,b) => a.val - b.val);
while (minHeap.length > 0) {
const smallest = minHeap.shift();
result.push(smallest.val);
const nextIndex = smallest.elementIndex + 1;
if (nextIndex < lists[smallest.listIndex].length) {
minHeap.push({ val: lists[smallest.listIndex][nextIndex], listIndex: smallest.listIndex, elementIndex: nextIndex });
minHeap.sort((a,b) => a.val - b.val);
}
}
return result;
}
console.log(mergeKLists(lists));Solution
Step 1: Initialize min heap with first elements
minHeap starts with {1,0,0}, {1,1,0}, {2,2,0} sorted as [1,1,2].Step 2: Extract smallest and add next elements
Extract 1 from list 0, add 4; extract 1 from list 1, add 3; extract 2 from list 2, add 6; continue until all elements merged.Final Answer:
[1,1,2,3,4,4,5,6] -> Option CQuick Check:
Merged sorted list = [1,1,2,3,4,4,5,6] [OK]
- Not sorting minHeap after each insertion
- Forgetting to add next element from same list
- Returning concatenated lists instead of merged
function mergeKLists(lists) {
const minHeap = [];
const result = [];
for (let i = 0; i < lists.length; i++) {
minHeap.push({ val: lists[i][0], listIndex: i, elementIndex: 0 });
}
minHeap.sort((a,b) => a.val - b.val);
while (minHeap.length > 0) {
const smallest = minHeap.shift();
result.push(smallest.val);
const nextIndex = smallest.elementIndex + 1;
if (nextIndex < lists[smallest.listIndex].length) {
minHeap.push({ val: lists[smallest.listIndex][nextIndex], listIndex: smallest.listIndex, elementIndex: nextIndex });
minHeap.sort((a,b) => a.val - b.val);
}
}
return result;
}Solution
Step 1: Check minHeap maintenance inside loop
After pushing a new element, minHeap must be sorted to keep smallest element at front.Step 2: Identify missing sorting
The code pushes new elements but does not sort minHeap again, breaking the min heap property.Final Answer:
Missing sorting minHeap after pushing new element inside the loop -> Option DQuick Check:
Sort after push to maintain min heap [OK]
- Forgetting to sort minHeap after push
- Confusing shift() and pop() usage
- Not pushing initial elements into minHeap
K sorted linked lists, which approach best optimizes the time complexity when merging them using a min heap?Solution
Step 1: Analyze time complexity of inserting all elements at once
Inserting all elements at once leads to O(N log N) where N is total elements, which is less efficient.Step 2: Understand dynamic insertion approach
Inserting only first elements and dynamically adding next elements keeps heap size at K, leading to O(N log K) time, which is optimal.Final Answer:
Insert only the first element of each list into the min heap, then extract and insert next elements dynamically -> Option AQuick Check:
Dynamic insertion = O(N log K) best [OK]
- Inserting all elements at once causing slow performance
- Ignoring heap size impact on complexity
- Using simple concatenation and sort which is inefficient
Ready to prove it?
Pass the test and this pattern moves unknown
