- 分组
- 组内排序(每5个一组,组内排序,组间不排序)
- 中位数拿出组成N/5大小的新数组(new_arr)
- 递归调用bfprt(new_arr,new_arr.length/2);,拿到返回值num
- 根据num值划分左中右,来找是否命中第k小的数
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[] res=new int[arr.length];
for(int i=0;i<res.length;i++) {
res[i]=arr[i];
}
return res;
}
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);
}
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++) {
int beginI=begin+5*i;
int endI=beginI+4;
mArr[i]=getMedian(arr, beginI, Math.min(end, endI));
}
return bfprt(mArr, 0, mArr.length-1, mArr.length/2);
}
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) {
for(int i=begin+1;i!=end+1;i++)
for(int j=i;i!=begin;j--) {
if(arr[j-1]>arr[j])
swap(arr, j-1, j);
else
break;
}
}
public static int[] partition(int[] arr,int begin,int end,int pivotValue) {
int left=begin-1;
int right=end-1;
int cur=begin;
while(cur!=right) {
if(arr[cur]<pivotValue) {
swap(arr, ++left, cur++);
}
else if(arr[cur]>pivotValue) {
swap(arr, cur, --right);
}
else
cur++;
}
int[] range=new int[2];
range[0]=left+1;
range[1]=right-1;
return range;
}
public static void swap(int[] arr,int i,int j) {
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}