Add MergeKSortedArrays algorithm (#5838)

This commit is contained in:
Hardik Pawar
2024-10-26 17:49:37 +05:30
committed by GitHub
parent 04e421b837
commit 9e1dd86a08
3 changed files with 103 additions and 0 deletions

View File

@ -179,6 +179,7 @@
* [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)
* [MedianFinder](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/heaps/MedianFinder.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
@ -860,6 +861,7 @@
* [KthElementFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/KthElementFinderTest.java)
* [LeftistHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java)
* [MedianFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java)
* [MergeKSortedArraysTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MergeKSortedArraysTest.java)
* [MinPriorityQueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java)
* lists
* [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)

View File

@ -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;
}
}

View File

@ -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}));
}
}