第一步:将给定的一串数字以5为一组,分好组
第二步:将分组的数据排好序
第三步:创建中位数数组,获取每个分组的中位数
第四步:循环第三步:直到中位数数组中只有一个数,那就是我们需要的比较数字
第五步:利用partition,小于该数的放左边,等于放中间,大于放右边
第六步:循环第五步,得到我们想要的第i个数
public static int getMinKNumsByBFPRT(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)
//在begin和end范围上求第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])//[0]和[1]是相同区域的两个边界
{
return arr[i];
}
else if(i<pivotRange[0])
{
return bfprt(arr,begin,pivotRange[0]-1,i);//i在左边界
}
else
{
return bfprt(arr,pivotRange[1]+1,end,i);//i在右边界
}
}
public static int medianofMedians(int []arr,int begin,int end)//将数组5个一组分组
{
int num=end-begin+1;
int offset=num%5==0?0:1;//是否整除5,整除就是0,有余数就是1
int []mArr=new int[num/5+offset];//
for(int i=0;i<mArr.length;i++)
{
int beginI=begin+i*5;
int endI=beginI+4;
mArr[i]=getMedian(arr,beginI,Math.min(end, endI));//获得5个一组分组中的中位数
}
return bfprt(mArr,0,mArr.length-1,mArr.length/2);//递归得到mArr的中位数
}
public static int getMedian(int []arr,int begin,int end)
{
insertionSort(arr,begin,end);//将5个一组的5个数排好序
int sum=end+begin;
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;j!=begin;j--)
{
if(arr[j-1]>arr[j])
{
swap(arr,j-1,j);
}
else
{
break;
}
}
}
}
public static void swap(int [] arr,int index1,int index2)
{
int tmp=arr[index1];
arr[index1]=arr[index2];
arr[index2]=tmp;
}
public static int [] partition(int []arr,int begin,int end,int pivotValue)
//pivotValue是用来比较的值
{
int small=begin-1;//小于区域
int cur=begin;//当前指针
int big=end+1;//大于区域
while(cur!=big)
{
if(arr[cur]<pivotValue)
{
swap(arr,++small,cur++);
}else if(arr[cur]>pivotValue)
{
swap(arr,cur,--big);
}else
{
cur++;
}
}
int []range=new int[2];
range[0]=small+1;
range[1]=big-1;
return range;
}
public static void main(String[] args) {
int[] arr = { 1, 3, 2, 5, 9 };
// 测试普通方法
System.out.println(getMinKNumsByBFPRT(arr,1));
System.out.println(getMinKNumsByBFPRT(arr,2));
System.out.println(getMinKNumsByBFPRT(arr,3));
System.out.println(getMinKNumsByBFPRT(arr,4));
System.out.println(getMinKNumsByBFPRT(arr,5));
}