Skip to content

feat: Add MergeKSortedArrays new algorithm with Junit tests #5838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Oct 26, 2024
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
* [HeapElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/HeapElement.java)
* [LeftistHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java)
* [MaxHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MaxHeap.java)
* [MergeKSortedArrays](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MergeKSortedArrays.java)
* [MinHeap](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MinHeap.java)
* [MinPriorityQueue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java)
* lists
Expand Down Expand Up @@ -802,6 +803,7 @@
* heaps
* [FibonacciHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/FibonacciHeapTest.java)
* [LeftistHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java)
* [MergeKSortedArraysTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MergeKSortedArraysTest.java)
* lists
* [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)
* [CreateAndDetectLoopTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CreateAndDetectLoopTest.java)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.thealgorithms.datastructures.heaps;

import java.util.Comparator;
import java.util.PriorityQueue;

/**
* This class provides a method to merge multiple sorted arrays into a single sorted array.
* It utilizes a min-heap to efficiently retrieve the smallest elements from each array.
*
* Time Complexity: O(n * log k), where n is the total number of elements across all arrays
* and k is the number of arrays.
*
* Space Complexity: O(k) for the heap, where k is the number of arrays.
*
* @author Hardvan
*/
public final class MergeKSortedArrays {
private MergeKSortedArrays() {
}

/**
* Merges k sorted arrays into one sorted array using a min-heap.
* Steps:
* 1. Create a min-heap to store elements in the format: {value, array index, element index}
* 2. Add the first element from each array to the heap
* 3. While the heap is not empty, remove the smallest element from the heap
* and add it to the result array. If there are more elements in the same array,
* add the next element to the heap.
* Continue until all elements have been processed.
* The result array will contain all elements in sorted order.
* 4. Return the result array.
*
* @param arrays a 2D array, where each subarray is sorted in non-decreasing order
* @return a single sorted array containing all elements from the input arrays
*/
public static int[] mergeKArrays(int[][] arrays) {
PriorityQueue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));

int totalLength = 0;
for (int i = 0; i < arrays.length; i++) {
if (arrays[i].length > 0) {
minHeap.offer(new int[] {arrays[i][0], i, 0});
totalLength += arrays[i].length;
}
}

int[] result = new int[totalLength];
int index = 0;
while (!minHeap.isEmpty()) {
int[] top = minHeap.poll();
result[index++] = top[0];

if (top[2] + 1 < arrays[top[1]].length) {
minHeap.offer(new int[] {arrays[top[1]][top[2] + 1], top[1], top[2] + 1});
}
}

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.thealgorithms.datastructures.heaps;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;

import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

public class MergeKSortedArraysTest {

@ParameterizedTest
@MethodSource("provideTestCases")
public void testMergeKArrays(int[][] arrays, int[] expected) {
assertArrayEquals(expected, MergeKSortedArrays.mergeKArrays(arrays));
}

private static Stream<Arguments> provideTestCases() {
return Stream.of(
// Basic test case with multiple arrays
Arguments.of(new int[][] {{1, 4, 5}, {1, 3, 4}, {2, 6}}, new int[] {1, 1, 2, 3, 4, 4, 5, 6}),

// Edge case: All arrays are empty
Arguments.of(new int[][] {{}, {}, {}}, new int[] {}),

// Edge case: One array is empty
Arguments.of(new int[][] {{1, 3, 5}, {}, {2, 4, 6}}, new int[] {1, 2, 3, 4, 5, 6}),

// Single array
Arguments.of(new int[][] {{1, 2, 3}}, new int[] {1, 2, 3}),

// Arrays with negative numbers
Arguments.of(new int[][] {{-5, 1, 3}, {-10, 0, 2}}, new int[] {-10, -5, 0, 1, 2, 3}),

// Arrays with duplicate elements
Arguments.of(new int[][] {{1, 1, 2}, {1, 3, 3}, {2, 2, 4}}, new int[] {1, 1, 1, 2, 2, 2, 3, 3, 4}),

// Edge case: Arrays of varying lengths
Arguments.of(new int[][] {{1, 2}, {3}, {4, 5, 6, 7}}, new int[] {1, 2, 3, 4, 5, 6, 7}));
}
}