题目:EPI
提示:
1、求出中位数,时间复杂度O(n);
2、生成最大堆,比较规则是根据该数与中位数的差值的大小。把前k个数压入堆。第k个数开始,若与中位数的差值小于堆顶的数与中位数的差值,则把堆顶弹出,该数入堆。
//返回下标为k的数值res,同时原数组被改变,第k位是res,k位之前小于res,k位之后大于等于res
//k大于等于零
double Kth_number(vector<double> &num, int left0, int right0, int k)
{
double x = num[left0];
if (left0 == right0)
{
if ( k == left0)
return num[left0];
else
throw new exception("error");
}
int left = left0, right = right0;
while (left < right)
{
while (left < right && num[right] >= x)
right--;
if (left < right)
{
num[left] = num[right];
left++;
}
while (left < right && num[left] < x)
left++;
if (left < right)
{
num[right] = num[left];
right--;
}
}
num[left] = x;
if (left == k)
return num[k];
else if (left>k)
return Kth_number(num, left0, left - 1, k);
else
return Kth_number(num, left + 1, right0, k);
}
double find_middle_number(vector<double> &num)
{
if (num.empty())
throw new exception("error");
int len = num.size();
if (len % 2 == 0)//数组长度为偶数
{
double a = Kth_number(num, 0, len - 1, len / 2 - 1);
double b = Kth_number(num, len / 2, len - 1, len / 2);
return (a + b) / 2;
}
else
return Kth_number(num, 0, len - 1, len / 2);
}
class compare_closest
{
public:
static double mid;
const bool operator()(const double a, const double b)const
{
return fabs(a - mid) < fabs(b - mid);
}
};
double compare_closest::mid = 0;
vector<double> find_k_closest_to_middlenumber(vector<double> num, const int k)
{
if (num.empty() || k <= 0)
throw new exception("error");
if (k >= num.size())
return vector<double>(num);
compare_closest::mid = find_middle_number(num);
int middle = compare_closest::mid;
priority_queue<double, vector<double>, compare_closest > max_heap;
for (int i = 0; i < k; i++)
{
max_heap.push(num[i]);
}
double diff = fabs(max_heap.top() - middle);
for (int i = k; i < num.size(); i++)
{
if (fabs(num[i] - middle) < diff)
{
max_heap.pop();
max_heap.push(num[i]);
diff = fabs(max_heap.top() - middle);
}
}
vector<double> res;
while (!max_heap.empty())
{
res.push_back(max_heap.top());
max_heap.pop();
}
return res;
}