public class Code01_FindMinKth {
public static void main(String[] args) {
int testTime = 5000;
int length = 200;
int max = 5000;
for (int i = 0; i < testTime; i++) {
int[] arr = generateArray(length,max);
int k = (int)(Math.random()*arr.length+1);
// for (int j = 0; j < arr.length; j++) {
// System.out.print(arr[j]+" ");
// }
// System.out.println("k="+k);
int ans1 = minKth1(arr,k);
int ans2 = minKth2(arr,k);
int ans3 = minKth3(arr,k);
if(ans1 != ans2 || ans1 != ans3){
System.out.println("no oops!");
}
}
System.out.println("yes");
}
// 方法一: 迭代调用
public static int minKth1(int[]arr, int k){
int[] copy= arrayCopy(arr);
int L = 0;
int R = copy.length-1;
while(L<R){
int pivot = copy[L+(int)Math.random()*(R-L+1)];
int[] ragne = partition(copy,L,R,pivot);
if(k-1<ragne[0]){
R = ragne[0]-1;
}else if(k-1 > ragne[1]){
L = ragne[1]+1;
}else{
return copy[k-1];
}
}
return copy[L];
}
// 方法二: 递归调用
public static int minKth2(int[]arr, int k){
int[] copy= arrayCopy(arr);
return process2(copy, 0, copy.length-1,k-1);
}
// 方法三: bfprt方法调用
public static int minKth3(int[]arr, int k){
int[] copy= arrayCopy(arr);
return bfprt(copy, 0, copy.length-1,k-1);
}
public static int bfprt(int[] arr, int L, int R, int index){
if(L == R){
return arr[L];
}
int pivot = medianOfMedians(arr,L,R);
int[] range = partition(arr,L,R,pivot);
if(index>=range[0] && index<=range[1]){
return arr[index];
}else if(index<range[0]){
return bfprt(arr, L, range[0]-1,index);
}else{
return bfprt(arr,range[1]+1,R,index);
}
}
/*
* arr[L...R] 五个数一组
* 每个小组内部排序
* 每个小组中位数领出来,组成marr
* marr中的中位数,返回
*/
public static int medianOfMedians(int[] arr, int L, int R){
int size = R - L + 1;
int offset = size%5 == 0 ? 0 : 1;
int[] mArr = new int[size/5+offset];
for (int team = 0; team<mArr.length; team++){
int teamFirst = L+team*5;
mArr[team] = getMedian(arr,teamFirst,Math.min(R, teamFirst+4));
}
// marr中找到中位数
return bfprt(mArr,0,mArr.length-1,mArr.length/2);
}
public static int getMedian(int[]arr, int L, int R){
insertionSort(arr,L,R);
return arr[(L+R)/2]; // 返回中位数
}
// 插入排序
public static void insertionSort(int[]arr, int L, int R){
for (int i = L+1; i <= R; i++) {
for (int j = i-1; j >=L && arr[j]>arr[j+1]; j--) {
swap(arr,j,j+1);
}
}
}
public static int[] generateArray(int lenght, int max){
int[] arr = new int[(int)(Math.random()*lenght)+1];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)(Math.random()*max+1);
}
//System.out.println(arr.length);
return arr;
}
public static int[] arrayCopy(int [] arr){
int[] copy= new int[arr.length];
for (int i = 0; i < arr.length; i++) {
copy[i] = arr[i];
}
return copy;
}
public static int process2(int[] arr, int L, int R, int index){
if(L == R){
return arr[L];
}
//System.out.println(R+" "+L);
//int pivot = arr[L+(int)(Math.random()*(R-L+1))];
int pivot = arr[L];
int[] range = partition(arr,L,R, pivot);
if(index>=range[0] && index<=range[1]){
return arr[index];
}else if(index<range[0]){
return process2(arr, L, range[0]-1,index);
}else{
return process2(arr, range[1]+1,R, index);
}
}
public static int[] partition(int[]arr, int L, int R, int pivot){
int less = L-1;
int more = R+1;
int cur = L;
while(cur < more){
if(arr[cur] < pivot){
//1 2 3 4 5 6 6 6 6 7,2,9
swap(arr,++less,cur++);
}else if(arr[cur] == pivot){
cur++;
}else{
swap(arr, --more,cur);
}
}
return new int[]{less+1,more-1};
}
public static void swap(int[]arr, int l, int r){
int t = arr[l];
arr[l] = arr[r];
arr[r] = t;
}
}
常考数据结构与算法-找到第k小的数(迭代,递归,bfprt)
最新推荐文章于 2022-02-25 00:13:36 发布
本文介绍了一个名为'Code01_FindMinKth'的Java程序,通过三种不同的方法(minKth1, minKth2, minKth3)实现查找数组中第k小的元素。方法一使用迭代和分区,方法二递归,方法三是快速选择(BFPRT)。通过测试比较它们的性能,确保结果一致性。
摘要由CSDN通过智能技术生成