diff --git a/src/main/java/com/thealgorithms/others/BFPRT.java b/src/main/java/com/thealgorithms/others/BFPRT.java index 1a5b44180..58c6d4e56 100644 --- a/src/main/java/com/thealgorithms/others/BFPRT.java +++ b/src/main/java/com/thealgorithms/others/BFPRT.java @@ -1,14 +1,22 @@ package com.thealgorithms.others; -import java.util.Arrays; - /** - * BFPRT algorithm. + * The BFPRT (Median of Medians) algorithm implementation. + * It provides a way to find the k-th smallest element in an unsorted array + * with an optimal worst-case time complexity of O(n). + * This algorithm is used to find the k smallest numbers in an array. */ public final class BFPRT { private BFPRT() { } + /** + * Returns the k smallest elements from the array using the BFPRT algorithm. + * + * @param arr the input array + * @param k the number of smallest elements to return + * @return an array containing the k smallest elements, or null if k is invalid + */ public static int[] getMinKNumsByBFPRT(int[] arr, int k) { if (k < 1 || k > arr.length) { return null; @@ -16,9 +24,9 @@ public final class BFPRT { int minKth = getMinKthByBFPRT(arr, k); int[] res = new int[k]; int index = 0; - for (int i = 0; i < arr.length; i++) { - if (arr[i] < minKth) { - res[index++] = arr[i]; + for (int value : arr) { + if (value < minKth) { + res[index++] = value; } } for (; index != res.length; index++) { @@ -27,17 +35,39 @@ public final class BFPRT { return res; } + /** + * Returns the k-th smallest element from the array using the BFPRT algorithm. + * + * @param arr the input array + * @param k the rank of the smallest element to find + * @return the k-th smallest element + */ public static int getMinKthByBFPRT(int[] arr, int k) { int[] copyArr = copyArray(arr); return bfprt(copyArr, 0, copyArr.length - 1, k - 1); } + /** + * Creates a copy of the input array. + * + * @param arr the input array + * @return a copy of the array + */ public static int[] copyArray(int[] arr) { int[] copyArr = new int[arr.length]; System.arraycopy(arr, 0, copyArr, 0, arr.length); return copyArr; } + /** + * BFPRT recursive method to find the k-th smallest element. + * + * @param arr the input array + * @param begin the starting index + * @param end the ending index + * @param i the index of the desired smallest element + * @return the k-th smallest element + */ public static int bfprt(int[] arr, int begin, int end, int i) { if (begin == end) { return arr[begin]; @@ -54,12 +84,12 @@ public final class BFPRT { } /** - * wikipedia: https://en.wikipedia.org/wiki/Median_of_medians . + * Finds the median of medians as the pivot element. * - * @param arr an array. - * @param begin begin num. - * @param end end num. - * @return median of medians. + * @param arr the input array + * @param begin the starting index + * @param end the ending index + * @return the median of medians */ public static int medianOfMedians(int[] arr, int begin, int end) { int num = end - begin + 1; @@ -71,12 +101,15 @@ public final class BFPRT { return bfprt(mArr, 0, mArr.length - 1, mArr.length / 2); } - public static void swap(int[] arr, int i, int j) { - int swap = arr[i]; - arr[i] = arr[j]; - arr[j] = swap; - } - + /** + * Partitions the array around a pivot. + * + * @param arr the input array + * @param begin the starting index + * @param end the ending index + * @param num the pivot element + * @return the range where the pivot is located + */ public static int[] partition(int[] arr, int begin, int end, int num) { int small = begin - 1; int cur = begin; @@ -90,12 +123,17 @@ public final class BFPRT { cur++; } } - int[] pivotRange = new int[2]; - pivotRange[0] = small + 1; - pivotRange[1] = big - 1; - return pivotRange; + return new int[] {small + 1, big - 1}; } + /** + * Finds the median of the elements between the specified range. + * + * @param arr the input array + * @param begin the starting index + * @param end the ending index + * @return the median of the specified range + */ public static int getMedian(int[] arr, int begin, int end) { insertionSort(arr, begin, end); int sum = begin + end; @@ -103,6 +141,13 @@ public final class BFPRT { return arr[mid]; } + /** + * Sorts a portion of the array using insertion sort. + * + * @param arr the input array + * @param begin the starting index + * @param end the ending index + */ public static void insertionSort(int[] arr, int begin, int end) { if (arr == null || arr.length < 2) { return; @@ -118,29 +163,16 @@ public final class BFPRT { } } - public static void main(String[] args) { - int[] arr = { - 11, - 9, - 1, - 3, - 9, - 2, - 2, - 5, - 6, - 5, - 3, - 5, - 9, - 7, - 2, - 5, - 5, - 1, - 9, - }; - int[] minK = getMinKNumsByBFPRT(arr, 5); - System.out.println(Arrays.toString(minK)); + /** + * Swaps two elements in an array. + * + * @param arr the input array + * @param i the index of the first element + * @param j the index of the second element + */ + public static void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; } } diff --git a/src/test/java/com/thealgorithms/others/BFPRTTest.java b/src/test/java/com/thealgorithms/others/BFPRTTest.java new file mode 100644 index 000000000..bb7c8f074 --- /dev/null +++ b/src/test/java/com/thealgorithms/others/BFPRTTest.java @@ -0,0 +1,34 @@ +package com.thealgorithms.others; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + +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; + +class BFPRTTest { + + @ParameterizedTest + @MethodSource("minKNumsTestData") + void testGetMinKNumsByBFPRT(int[] arr, int k, int[] expected) { + int[] result = BFPRT.getMinKNumsByBFPRT(arr, k); + assertArrayEquals(expected, result); + } + + private static Stream minKNumsTestData() { + return Stream.of(Arguments.of(new int[] {11, 9, 1, 3, 9, 2, 2, 5, 6, 5, 3, 5, 9, 7, 2, 5, 5, 1, 9}, 5, new int[] {1, 1, 2, 2, 2}), Arguments.of(new int[] {3, 2, 1}, 2, new int[] {1, 2}), Arguments.of(new int[] {7, 5, 9, 1, 3, 8, 2, 4, 6}, 3, new int[] {1, 2, 3})); + } + + @ParameterizedTest + @MethodSource("minKthTestData") + void testGetMinKthByBFPRT(int[] arr, int k, int expected) { + int result = BFPRT.getMinKthByBFPRT(arr, k); + assertEquals(expected, result); + } + + private static Stream minKthTestData() { + return Stream.of(Arguments.of(new int[] {3, 2, 1}, 2, 2), Arguments.of(new int[] {7, 5, 9, 1, 3, 8, 2, 4, 6}, 3, 3), Arguments.of(new int[] {5, 8, 6, 3, 2, 7, 1, 4}, 4, 4)); + } +}