一、简介
所谓的Top K问题其实就是找数组中最大的前k个值。为此,只要我们能够找到数组中的第k大值,那么Top K问题就会迎刃而解。在此声明一下,本文写的方法肯定不是最好的。不过最近看了几个题,其核心都是找第k大的值。这里,我只是总结下而已。
二、举例说明
例如:对于数组a[N],取其最大的前k个数。
1、用数组b[k]建立初始小顶堆(用0初始化数组b即可);
2、从i=1,2,…,N依次遍历a:
2.1、若:a[i] > b[0],用a[i]取代b[0],同时重新调整小顶堆;
2.2、否则,保持b[0]不变。
3、重复步骤2,一直到i=N为止。
三、详细代码
3.1、小顶堆
#define NUM 10
typedef int ELEM;
void heap(ELEM a[],int left,int right)
{
if (left >= right)
return ;
int r = left;
int LChild = 2*r+1;
int Child = LChild;
ELEM temp = a[r];
while(LChild <= right)
{
if(LChild < right && a[LChild] > a[LChild+1])
Child = LChild + 1;
if(temp > a[Child])
{
a[r] = a[Child];
r = Child;
LChild = 2*r+1;
Child = LChild;
}
else
break;
}
a[r] = temp;
return;
}
3.2、主函数
int main(int argc,char **argv)
{
if(argc < 2)
{
printf("参数数量不够!");
return 0;
}
int i;
int k = atoi(argv[1]);
ELEM a[NUM] = {2,5,3,1,6,13,15,1859,131,13};
ELEM* b = (ELEM*)malloc(k*sizeof(ELEM));
memset(b,0,k*sizeof(ELEM));
for(i = 0;i < NUM;i++)
{
if(a[i] > b[0])
{
b[0] = a[i];
heap(b,0,k-1);
}
}
printf("a中最大的k个数:");
for (i = 0;i < k;i++)
printf("%d ",b[i]);
free(b);
b = NULL;
return 0;
}
3.3、输出结果
当k=5
时,上述代码输出结果为:
a中最大的k个数:13 13 131 1859 15
(这里的k个数是无序的)
4、说明
如果要取前k
个最小的数,将上述小顶堆改为大顶堆再将主函数中
if(a[i] > b[0])
{
b[0] = a[i]
heap(b,0,k-1)
}
的“a[i] > b[0]
“改为”a[i] < b[0]
“即可。
上述思想主要参考自“编程之美,p142~p144”。