问题描述:给出一组数据,如:整型数组 int a[]={10,1,3,6,9,39,20,12,33,54} 用尽可能快的方法找出第K大的位置(如:k=5时即第5大的数据应为12)。
分析问题:首先,如果求解问题是需要从一组数据寻找最值时(最大值或者最小值时)可能比较方便,一般作法是先排序,然后最首或者尾位置即可。
但现在需要求解的不一定是指最值,而是求第K大最值。那么同样处理思路是分步,即先排序然后求对应K位置。
经过简单的分析,下面给出Demo(C语言)
//下面为排序设计两个函数
int partition(const int * na, int low, int hight);//标注位置
int qsort(const int * na, int low, int high, int nNeed);//改进快速排序
/*
*寻找目标位置函数Find
*参数说明:
* narray:给定数组
* n:数组长度
* K:需要寻找第K大数值
*返回寻找的结果索引
*/
int Find(const int * narray, const int n, const int K)
{
if ( n < 1)
return -1;
if ( (K < 1) || (K > n) )
return -2;
int * pN = new int[n];
for (int i = 0; i < n; i++)
{
pN[i] = narray[i];
}
//在新数组中寻找第K最值数据(非索引位置)
int nVal = qsort(pN, 0, n-1, k-1);
//在源数组中寻找第K最值索引位置
for (int i = 0; i < n; i++)
{
if ( narray[i] == nVal)
return i;
}
}
/*
* 寻找索引位置,快速排序的位置处理部分
*/
int partition(const int * na, int low, int hight) {
int nTmp = na[low];
while (low < high )
{
while (low < high && na[high] <= nTmp)
{
high--;
}
na[low] = na[high];
while (low < high && na[low] >= nTmp)
{
low++;
}
na[higt] = na[low];
}
na[low] = nTmp;
return low;
}
/**
* 改造的快速排序算法,只排需要取得第K大前的元素。
*返回第K最值数据,不是索引位置
* 参数说明确:
* na : 指向数组索引.
* low : 所需要进行处理元素的下界
* hight :所需要进行处理元素的上界
* nNeed : 优先处理的元素.
*
*/
int qsort(const int * na, int low, int high, int nNeed) {
int nFound = partition(na, low, high);
if (nFound == nNeed)
{
return na[nFound];
}
if (nFound < nNeed) {
return qsort(na, nFound, high);
}
if (nFound > nNeed) {
return qsort(na, low, nFound);
}
}
通过以上算法,我们可以快速实现求解过程,最好情况下时间复杂为:O(n),最差情况为:O(nlogn)。实现局部排序
但不知道还有没有其他更优化的算法。期待大家的回答