diff --git a/Others/BFPRT.java b/Others/BFPRT.java new file mode 100644 index 00000000..7b2adcc7 --- /dev/null +++ b/Others/BFPRT.java @@ -0,0 +1,129 @@ +package Others; + +import java.util.Arrays; + +/** + * BFPRT algorithm. + */ +public class BFPRT { + + public static int[] getMinKNumsByBFPRT(int[] arr, int k) { + if (k < 1 || k > arr.length) { + return null; + } + 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 (; index != res.length; index++) { + res[index] = minKth; + } + return res; + } + + public static int getMinKthByBFPRT(int[] arr, int k) { + int[] copyArr = copyArray(arr); + return bfprt(copyArr, 0, copyArr.length - 1, k - 1); + } + + public static int[] copyArray(int[]arr) { + int[] copyArr = new int[arr.length]; + for(int i = 0; i < arr.length; i++) { + copyArr[i] = arr[i]; + } + return copyArr; + } + + public static int bfprt(int[] arr, int begin, int end, int i) { + if (begin == end) { + return arr[begin]; + } + int pivot = medianOfMedians(arr, begin, end); + int[] pivotRange = partition(arr, begin, end, pivot); + if (i >= pivotRange[0] && i <= pivotRange[1]) { + return arr[i]; + } else if (i < pivotRange[0]) { + return bfprt(arr, begin, pivotRange[0] - 1, i); + } else { + return bfprt(arr, pivotRange[1] + 1, end, i); + } + } + + /** + * wikipedia: https://en.wikipedia.org/wiki/Median_of_medians . + * @param arr an array. + * @param begin begin num. + * @param end end num. + * @return median of medians. + */ + public static int medianOfMedians(int[] arr, int begin, int end) { + int num = end - begin + 1; + int offset = num % 5 == 0 ? 0 : 1; + int[] mArr = new int[num / 5 + offset]; + for (int i = 0;i < mArr.length;i++) { + mArr[i] = getMedian(arr, begin + i * 5, Math.min(end, begin + i * 5 + 4)); + } + 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; + } + + public static int[] partition(int[] arr,int begin,int end,int num) + { + int small=begin-1; + int cur=begin; + int big=end+1; + while(cur!=big) + { + if (arr[cur]num) + { + swap(arr,--big,cur); + } else { + cur++; + } + } + int[] pivotRange=new int[2]; + pivotRange[0]=small+1; + pivotRange[1]=big-1; + return pivotRange; + } + + public static int getMedian(int[] arr, int begin, int end) { + insertionSort(arr, begin, end); + int sum = begin + end; + int mid = sum / 2 + (sum % 2); + return arr[mid]; + } + + public static void insertionSort(int[] arr, int begin, int end) { + if (arr == null || arr.length < 2) { + return; + } + for (int i = begin + 1;i != end + 1;i++) { + for (int j = i;j != begin;j--) { + if (arr[j - 1] > arr[j]) { + swap(arr, j - 1, j); + } else { + break; + } + } + } + } + + 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)); + } +}