Skip to content

Commit 38df2cc

Browse files
committed
feat: Add MergeKSortedArrays new algorithm with Junit tests
1 parent 30504c1 commit 38df2cc

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.thealgorithms.datastructures.heaps;
2+
3+
import java.util.Comparator;
4+
import java.util.PriorityQueue;
5+
6+
/**
7+
* This class provides a method to merge multiple sorted arrays into a single sorted array.
8+
* It utilizes a min-heap to efficiently retrieve the smallest elements from each array.
9+
*
10+
* Time Complexity: O(n * log k), where n is the total number of elements across all arrays
11+
* and k is the number of arrays.
12+
*
13+
* Space Complexity: O(k) for the heap, where k is the number of arrays.
14+
*
15+
* @author Hardvan
16+
*/
17+
public final class MergeKSortedArrays {
18+
private MergeKSortedArrays() {
19+
}
20+
21+
/**
22+
* Merges k sorted arrays into one sorted array using a min-heap.
23+
* Steps:
24+
* 1. Create a min-heap to store elements in the format: {value, array index, element index}
25+
* 2. Add the first element from each array to the heap
26+
* 3. While the heap is not empty, remove the smallest element from the heap
27+
* and add it to the result array. If there are more elements in the same array,
28+
* add the next element to the heap.
29+
* Continue until all elements have been processed.
30+
* The result array will contain all elements in sorted order.
31+
* 4. Return the result array.
32+
*
33+
* @param arrays a 2D array, where each subarray is sorted in non-decreasing order
34+
* @return a single sorted array containing all elements from the input arrays
35+
*/
36+
public static int[] mergeKArrays(int[][] arrays) {
37+
PriorityQueue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
38+
39+
int totalLength = 0;
40+
for (int i = 0; i < arrays.length; i++) {
41+
if (arrays[i].length > 0) {
42+
minHeap.offer(new int[] {arrays[i][0], i, 0});
43+
totalLength += arrays[i].length;
44+
}
45+
}
46+
47+
int[] result = new int[totalLength];
48+
int index = 0;
49+
while (!minHeap.isEmpty()) {
50+
int[] top = minHeap.poll();
51+
result[index++] = top[0];
52+
53+
if (top[2] + 1 < arrays[top[1]].length) {
54+
minHeap.offer(new int[] {arrays[top[1]][top[2] + 1], top[1], top[2] + 1});
55+
}
56+
}
57+
58+
return result;
59+
}
60+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.thealgorithms.datastructures.heaps;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
5+
import java.util.stream.Stream;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.Arguments;
8+
import org.junit.jupiter.params.provider.MethodSource;
9+
10+
public class MergeKSortedArraysTest {
11+
12+
/**
13+
* Parameterized test for merging multiple sorted arrays.
14+
* Each test case provides input arrays and the expected merged output.
15+
*
16+
* @param arrays the input 2D array of sorted arrays
17+
* @param expected the expected merged sorted array
18+
*/
19+
@ParameterizedTest
20+
@MethodSource("provideTestCases")
21+
public void testMergeKArrays(int[][] arrays, int[] expected) {
22+
assertArrayEquals(expected, MergeKSortedArrays.mergeKArrays(arrays));
23+
}
24+
25+
/**
26+
* Provides various test cases including edge cases for merging sorted arrays.
27+
*
28+
* @return a stream of test arguments containing input arrays and expected outputs
29+
*/
30+
private static Stream<Arguments> provideTestCases() {
31+
return Stream.of(
32+
// Basic test case with multiple arrays
33+
Arguments.of(new int[][] {{1, 4, 5}, {1, 3, 4}, {2, 6}}, new int[] {1, 1, 2, 3, 4, 4, 5, 6}),
34+
35+
// Edge case: All arrays are empty
36+
Arguments.of(new int[][] {{}, {}, {}}, new int[] {}),
37+
38+
// Edge case: One array is empty
39+
Arguments.of(new int[][] {{1, 3, 5}, {}, {2, 4, 6}}, new int[] {1, 2, 3, 4, 5, 6}),
40+
41+
// Single array
42+
Arguments.of(new int[][] {{1, 2, 3}}, new int[] {1, 2, 3}),
43+
44+
// Arrays with negative numbers
45+
Arguments.of(new int[][] {{-5, 1, 3}, {-10, 0, 2}}, new int[] {-10, -5, 0, 1, 2, 3}),
46+
47+
// Arrays with duplicate elements
48+
Arguments.of(new int[][] {{1, 1, 2}, {1, 3, 3}, {2, 2, 4}}, new int[] {1, 1, 1, 2, 2, 2, 3, 3, 4}),
49+
50+
// Edge case: Arrays of varying lengths
51+
Arguments.of(new int[][] {{1, 2}, {3}, {4, 5, 6, 7}}, new int[] {1, 2, 3, 4, 5, 6, 7}));
52+
}
53+
}

0 commit comments

Comments
 (0)