从一组数据中寻找第K大的数

问题描述:给出一组数据,如:整型数组 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)。实现局部排序

但不知道还有没有其他更优化的算法。期待大家的回答

 

posted on 2010-10-22 17:20  陈国利  阅读(2344)  评论(4编辑  收藏  举报