/**
* 选出一个整数序列中,与中位数最接近的m个数。
*
* 1) 找出中位数,O(n)
* 2) 遍历,求出差值数组,保证为正值,O(n)
* 3) 求出最小的m个数, 选择排序,O(m*n), 更好的是用最小二叉堆,O(lgm*n)
*
*
*/
public class MidMDigits {
/**
* 获取中位数, 类似快排
* @param a
* @return
*/
public int getMiddle(int[] a, int begin, int end, int k){
assert(a != null);
assert(a.length > 0);
int p = partition(a, begin, end);
int leftCount = p - begin;
if(k == leftCount + 1){
return a[p];
}else if( k < leftCount+1){
return getMiddle(a, begin, p-1, k);
}else{
return getMiddle(a, p+1, end, k-leftCount-1);
}
}
public int[] getK(int[] a, final int m){
assert(true);
int k = 0;
if((a.length % 2) == 0){
k = a.length/2;
}else{
k = a.length/2 + 1;
}
int middle = getMiddle(a, 0, a.length-1, k);
int[] abs = getAbs(a, middle);
int[] result = new int[m];
for(int i=0; i<m; i++){
int maxP = i;
for(int j=i+1; j<a.length; j++){
if(abs[j] > abs[maxP]){
maxP = j;
}
}
if(maxP != i){
Tools.swap(abs, maxP, i);
Tools.swap(a, maxP, i);
}
result[i] = a[i];
}
return result;
}
private int[] getAbs(int[] a, int mid){
int[] abs = new int[a.length];
for(int i=0; i<a.length; i++){
int value = a[i] - mid;
if(value < 0){
value = -value;
}
abs[i] = value;
}
return abs;
}
private int partition(int[] a, int begin, int end){
int mid = a[end];
int p = begin;
for(int i=begin; i<end; i++){
if(a[i] < mid){
Tools.swap(a, i, p);
p++;
}
}
Tools.swap(a, p, end);
return p;
}
}
与中位数最接近的m个数
最新推荐文章于 2021-05-25 10:02:13 发布