#include<iostream>
#include<algorithm>
using namespace std;
int getMedian(int arr[], int begin, int end);
int* partition(int arr[],int L, int R, int pivotvalue);
void swap(int arr[], int i, int j);
int bfprt(int arr[], int begin, int end,int k);
int medianOfMedians(int arr[], int begin, int end);
int getMedian(int arr[], int begin, int end);
int main(){
int arr[] = {2,3,1,4,8,21,14,99,12};
cout << bfprt(arr,0,8,5);
return 0;
}
int* partition(int arr[],int L, int R, int pivotvalue){
int small = L-1;
int cur = L;
int big = R+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;
}
void swap(int arr[], int i, int j){
int temp = arr[i];
arr[i]= arr[j];
arr[j] = temp;
}
void show(int arr[], int length){
int i=0;
while(i<length){
cout << arr[i]<<endl;;
i++;
}
}
//找数组中 第K大的数
//begin 开始的下标, end 最后一个值所在的下标
int bfprt(int arr[], int begin, int end,int k){
//如果到了只有一个数的情况,那么不管第几大 都返回该数
if(begin == end){
return arr[begin];
}
int pivot = medianOfMedians(arr, begin, end);
int* pivotRange = partition(arr, begin, end, pivot);
//找到中位数 排序完后的位置,判断 要找的第K大的数 是不是在 中位数所处的下边范围内,如果在,那就找到了。
if(k >= pivotRange[0] && k <= pivotRange[1]){
return arr[k];
}else if(k < pivotRange[0]){
return bfprt(arr, begin, pivotRange[0]-1, k);
}else{
return bfprt(arr, pivotRange[1]+1,end ,k);
}
}
int medianOfMedians(int arr[], int begin, int end){
int num = end -begin +1;
int offset = num % 5 ==0 ? 0 : 1;
int length =num/5 + offset;
int* mArr = new int[length];
for(int i=0;i< length; i++){
int beginI = begin + i*5;
int endI = beginI + 4;
mArr[i] = getMedian(arr, beginI, min(end,endI));
}
return bfprt(mArr, 0, length-1, length/2);
}
int getMedian(int arr[], int begin, int end){
sort(arr+begin, arr+end);
int sum = end + begin;
int mid = sum /2 + sum%2;
return arr[mid];
}