← Back to All Patterns

K-way Merge Pattern

K-way Merge Animation

K Sorted Lists (K = 3):

List 0:
1
4
7
List 1:
2
5
8
List 2:
3
6
9

Min Heap (size = 0):

Empty (All merged!)

Merged Result:

Empty (Starting...)

Start: We have 3 sorted lists. Use min heap to merge efficiently!

Speed:
Step 1 of 11

🎯 Explain Like I'm 5...

Imagine you and 2 friends each have a pile of numbered cards 🎴 (already in order!). You want to combine them into ONE big sorted pile!

🃏 Three Piles:

  • Your pile: 1, 4, 7 (smallest on top!)
  • Friend 1's pile: 2, 5, 8
  • Friend 2's pile: 3, 6, 9

🎯 The Merging Game:

  • Everyone shows their TOP card: 1, 2, 3
  • Pick the SMALLEST (1)! Put it in the new pile!
  • You flip your next card (4). Now tops are: 4, 2, 3
  • Pick smallest (2)! Friend 1 flips next card...
  • Keep going until ALL cards are in one pile!

Final pile: 1, 2, 3, 4, 5, 6, 7, 8, 9 - Perfect order! 🎉

🚀 The Magic: Use a special helper (min heap) that ALWAYS knows which card is smallest among all the tops! Instead of checking 3 piles each time, the helper just tells you "pick THIS one!" Super fast! ⚡

When Should You Use This Pattern?

  • Merging K sorted arrays/lists
  • Finding the smallest range covering elements from K lists
  • Finding the Kth smallest element in K sorted arrays
  • Problems with multiple sorted inputs

📝 Example 1: Merge K Sorted Lists

Merge K sorted linked lists into one sorted linked list.

Step-by-Step Thinking:

  1. Add the first node of each list to a min heap
  2. Pop smallest node from heap and add to result
  3. Add the next node from that list to heap
  4. Repeat until all nodes are processed
MergeKLists.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import java.util.*;
class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public class MergeKLists {
public static ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) {
return null;
}
// Min heap to track smallest node from each list
PriorityQueue<ListNode> minHeap =
new PriorityQueue<>((a, b) -> a.val - b.val);
// Add first node of each list to heap
for (ListNode node : lists) {
if (node != null) {
minHeap.offer(node);
}
}
// Build result list
ListNode dummy = new ListNode(0);
ListNode current = dummy;
while (!minHeap.isEmpty()) {
// Get smallest node
ListNode smallest = minHeap.poll();
current.next = smallest;
current = current.next;
// Add next node from that list
if (smallest.next != null) {
minHeap.offer(smallest.next);
}
}
return dummy.next;
}
public static void printList(ListNode head) {
while (head != null) {
System.out.print(head.val);
if (head.next != null) System.out.print(" -> ");
head = head.next;
}
System.out.println();
}
public static void main(String[] args) {
// List 1: 1 -> 4 -> 5
ListNode l1 = new ListNode(1);
l1.next = new ListNode(4);
l1.next.next = new ListNode(5);
// List 2: 1 -> 3 -> 4
ListNode l2 = new ListNode(1);
l2.next = new ListNode(3);
l2.next.next = new ListNode(4);
// List 3: 2 -> 6
ListNode l3 = new ListNode(2);
l3.next = new ListNode(6);
ListNode[] lists = {l1, l2, l3};
ListNode result = mergeKLists(lists);
System.out.print("Merged list: ");
printList(result);
// Output: 1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6
}
}

📝 Example 2: Kth Smallest in Sorted Matrix

Find the Kth smallest element in an n×n matrix where each row and column is sorted.

KthSmallestMatrix.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.util.*;
public class KthSmallestMatrix {
static class Element {
int val;
int row;
int col;
Element(int val, int row, int col) {
this.val = val;
this.row = row;
this.col = col;
}
}
public static int kthSmallest(int[][] matrix, int k) {
int n = matrix.length;
// Min heap to track smallest elements
PriorityQueue<Element> minHeap =
new PriorityQueue<>((a, b) -> a.val - b.val);
// Add first element of each row
for (int i = 0; i < Math.min(n, k); i++) {
minHeap.offer(new Element(matrix[i][0], i, 0));
}
// Extract k smallest elements
Element element = null;
for (int i = 0; i < k; i++) {
element = minHeap.poll();
// Add next element from same row
if (element.col + 1 < n) {
minHeap.offer(new Element(
matrix[element.row][element.col + 1],
element.row,
element.col + 1
));
}
}
return element.val;
}
public static void main(String[] args) {
int[][] matrix = {
{1, 5, 9},
{10, 11, 13},
{12, 13, 15}
};
int k = 8;
System.out.println("Kth smallest: " + kthSmallest(matrix, k));
// Output: 13
// Sorted: [1, 5, 9, 10, 11, 12, 13, 13, 15]
}
}

📝 Example 3: Smallest Range Covering K Lists

Find the smallest range that includes at least one number from each of the K lists.

SmallestRange.java
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.util.*;
public class SmallestRange {
static class Element {
int val;
int listIndex;
int elementIndex;
Element(int val, int listIndex, int elementIndex) {
this.val = val;
this.listIndex = listIndex;
this.elementIndex = elementIndex;
}
}
public static int[] smallestRange(List<List<Integer>> lists) {
// Min heap for smallest elements
PriorityQueue<Element> minHeap =
new PriorityQueue<>((a, b) -> a.val - b.val);
int currentMax = Integer.MIN_VALUE;
int rangeStart = 0;
int rangeEnd = Integer.MAX_VALUE;
// Add first element from each list
for (int i = 0; i < lists.size(); i++) {
int val = lists.get(i).get(0);
minHeap.offer(new Element(val, i, 0));
currentMax = Math.max(currentMax, val);
}
// Process elements
while (minHeap.size() == lists.size()) {
Element smallest = minHeap.poll();
int currentMin = smallest.val;
// Update range if smaller
if (rangeEnd - rangeStart > currentMax - currentMin) {
rangeStart = currentMin;
rangeEnd = currentMax;
}
// Add next element from same list
if (smallest.elementIndex + 1 < lists.get(smallest.listIndex).size()) {
int nextVal = lists.get(smallest.listIndex).get(smallest.elementIndex + 1);
minHeap.offer(new Element(nextVal, smallest.listIndex, smallest.elementIndex + 1));
currentMax = Math.max(currentMax, nextVal);
}
}
return new int[]{rangeStart, rangeEnd};
}
public static void main(String[] args) {
List<List<Integer>> lists = Arrays.asList(
Arrays.asList(4, 10, 15, 24, 26),
Arrays.asList(0, 9, 12, 20),
Arrays.asList(5, 18, 22, 30)
);
int[] range = smallestRange(lists);
System.out.println("Smallest range: [" + range[0] + ", " + range[1] + "]");
// Output: [20, 24]
// Contains: 20 from list2, 24 from list1, 22 from list3
}
}

🔑 Key Points to Remember

  • 1️⃣Use min heap to efficiently track smallest element across K lists
  • 2️⃣Store additional info in heap (which list, which index)
  • 3️⃣Time Complexity: O(N log K) where N is total elements, K is lists
  • 4️⃣Space Complexity: O(K) for the heap

💪 Practice Problems

  • Merge Sorted Array
  • Find Median from Data Stream
  • Kth Smallest Number in M Sorted Lists
  • Minimum Cost to Connect Ropes