🧠
Better Approach (Using Min Heap to Merge)
💡 This approach leverages a min heap to efficiently merge k sorted arrays by always picking the smallest current element among the arrays.
Intuition
Use a min heap to keep track of the smallest elements from each array. Extract the smallest element and add the next element from the same array to the heap until all elements are processed.
Algorithm
- Initialize a min heap.
- Insert the first element of each array into the heap along with array and element indices.
- While the heap is not empty, extract the smallest element and add it to the result.
- If the extracted element's array has more elements, insert the next element into the heap.
💡 The heap always contains the next smallest candidates from each array, ensuring efficient merging.
import heapq
def merge_k_sorted_arrays(arrays):
min_heap = []
result = []
# Initialize heap with first element of each array
for i, arr in enumerate(arrays):
if arr:
heapq.heappush(min_heap, (arr[0], i, 0))
while min_heap:
val, arr_idx, ele_idx = heapq.heappop(min_heap)
result.append(val)
if ele_idx + 1 < len(arrays[arr_idx]):
next_val = arrays[arr_idx][ele_idx + 1]
heapq.heappush(min_heap, (next_val, arr_idx, ele_idx + 1))
return result
# Driver code
if __name__ == '__main__':
arrays = [[1,4,5],[1,3,4],[2,6]]
print(merge_k_sorted_arrays(arrays))
Line Notes
min_heap = []Create a min heap to store the smallest elements from each array
for i, arr in enumerate(arrays):Iterate over each array with its index
heapq.heappush(min_heap, (arr[0], i, 0))Push the first element of each array with array and element indices
val, arr_idx, ele_idx = heapq.heappop(min_heap)Pop the smallest element from the heap along with its origin info
import java.util.*;
public class MergeKSortedArrays {
static class Element implements Comparable<Element> {
int value, arrIdx, eleIdx;
Element(int v, int a, int e) { value = v; arrIdx = a; eleIdx = e; }
public int compareTo(Element other) { return this.value - other.value; }
}
public static List<Integer> mergeKSortedArrays(List<List<Integer>> arrays) {
PriorityQueue<Element> minHeap = new PriorityQueue<>();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < arrays.size(); i++) {
if (!arrays.get(i).isEmpty()) {
minHeap.offer(new Element(arrays.get(i).get(0), i, 0));
}
}
while (!minHeap.isEmpty()) {
Element curr = minHeap.poll();
result.add(curr.value);
if (curr.eleIdx + 1 < arrays.get(curr.arrIdx).size()) {
int nextVal = arrays.get(curr.arrIdx).get(curr.eleIdx + 1);
minHeap.offer(new Element(nextVal, curr.arrIdx, curr.eleIdx + 1));
}
}
return result;
}
public static void main(String[] args) {
List<List<Integer>> arrays = Arrays.asList(
Arrays.asList(1,4,5),
Arrays.asList(1,3,4),
Arrays.asList(2,6)
);
System.out.println(mergeKSortedArrays(arrays));
}
}
Line Notes
static class Element implements Comparable<Element>Define a class to hold value and indices for heap ordering
PriorityQueue<Element> minHeap = new PriorityQueue<>();Create a min heap to store elements
minHeap.offer(new Element(arrays.get(i).get(0), i, 0));Add first element of each array to heap
Element curr = minHeap.poll();Extract smallest element from heap
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct Element {
int value, arrIdx, eleIdx;
Element(int v, int a, int e) : value(v), arrIdx(a), eleIdx(e) {}
bool operator>(const Element& other) const {
return value > other.value;
}
};
vector<int> mergeKSortedArrays(const vector<vector<int>>& arrays) {
priority_queue<Element, vector<Element>, greater<Element>> minHeap;
vector<int> result;
for (int i = 0; i < arrays.size(); i++) {
if (!arrays[i].empty()) {
minHeap.emplace(arrays[i][0], i, 0);
}
}
while (!minHeap.empty()) {
Element curr = minHeap.top();
minHeap.pop();
result.push_back(curr.value);
if (curr.eleIdx + 1 < arrays[curr.arrIdx].size()) {
minHeap.emplace(arrays[curr.arrIdx][curr.eleIdx + 1], curr.arrIdx, curr.eleIdx + 1);
}
}
return result;
}
int main() {
vector<vector<int>> arrays = {{1,4,5},{1,3,4},{2,6}};
vector<int> result = mergeKSortedArrays(arrays);
for (int num : result) cout << num << ' ';
cout << endl;
return 0;
}
Line Notes
struct ElementDefine a struct to hold value and indices for heap comparison
priority_queue<Element, vector<Element>, greater<Element>> minHeap;Create a min heap using greater comparator
minHeap.emplace(arrays[i][0], i, 0);Insert first element of each array into heap
Element curr = minHeap.top();Get smallest element from heap
class Element {
constructor(value, arrIdx, eleIdx) {
this.value = value;
this.arrIdx = arrIdx;
this.eleIdx = eleIdx;
}
}
function mergeKSortedArrays(arrays) {
const minHeap = [];
const result = [];
function heapPush(elem) {
minHeap.push(elem);
let i = minHeap.length - 1;
while (i > 0) {
let parent = Math.floor((i - 1) / 2);
if (minHeap[parent].value <= minHeap[i].value) break;
[minHeap[parent], minHeap[i]] = [minHeap[i], minHeap[parent]];
i = parent;
}
}
function heapPop() {
const top = minHeap[0];
const end = minHeap.pop();
if (minHeap.length > 0) {
minHeap[0] = end;
let i = 0;
while (true) {
let left = 2 * i + 1;
let right = 2 * i + 2;
let smallest = i;
if (left < minHeap.length && minHeap[left].value < minHeap[smallest].value) smallest = left;
if (right < minHeap.length && minHeap[right].value < minHeap[smallest].value) smallest = right;
if (smallest === i) break;
[minHeap[i], minHeap[smallest]] = [minHeap[smallest], minHeap[i]];
i = smallest;
}
}
return top;
}
for (let i = 0; i < arrays.length; i++) {
if (arrays[i].length > 0) {
heapPush(new Element(arrays[i][0], i, 0));
}
}
while (minHeap.length > 0) {
const curr = heapPop();
result.push(curr.value);
if (curr.eleIdx + 1 < arrays[curr.arrIdx].length) {
heapPush(new Element(arrays[curr.arrIdx][curr.eleIdx + 1], curr.arrIdx, curr.eleIdx + 1));
}
}
return result;
}
// Driver code
const arrays = [[1,4,5],[1,3,4],[2,6]];
console.log(mergeKSortedArrays(arrays));
Line Notes
class ElementDefine a class to hold value and indices for heap elements
function heapPush(elem)Insert element into min heap maintaining heap property
function heapPop()Remove and return smallest element from min heap
for (let i = 0; i < arrays.length; i++)Initialize heap with first element of each array
TimeO(N log k) where N is total elements, k is number of arrays
SpaceO(k) for heap + O(N) for output
Each element is pushed and popped from the heap once. Heap size is at most k, so operations take O(log k).
💡 For 100,000 elements and 100 arrays, this means about 100,000 * log2(100) ≈ 664,000 operations, which is efficient.
Interview Verdict: Accepted and efficient for large inputs
This is the standard optimal approach for merging k sorted arrays in interviews.