要找到数组中最小的k个数,只需要建立一个k大小的数组,或者在原数组中开辟一个大小为k的区间,用来保留k个数;
遍历原数组,如果有比k个数小的,就用该数去替换k数组中最大的,所以问题就转化成在k数组中找最大的数,最差效率为o((n-k)*k)
如果利用最大堆的特性,就能快速在k大小数组中找到最大的数,效率变成o((n-k)*logn)
代码如下:
void minKinArray(int *p,int nlen,int *result,int k)
{
if (p==NULL||nlen<k)
{
return;
}
for (int i=0;i<k;i++)
{
result[i]=p[i];
}
int max;
creatMaxHeap(result,k);
for (int i=k;i<nlen;i++)
{
max=result[0];
if (p[i]<max)
{
result[0]=p[i];
}
adjustHeap(result,k,0);
}
}
void printArray(int *p,int nlen)
{
if (p==NULL||nlen<=0)
{
return;
}
for (int i=0;i<nlen;i++)
{
cout<<p[i]<<'\t';
}
cout<<endl;
}
void creatMaxHeap(int *p,int nlen)
{
if (nlen<=1)
{
return;
}
int index=((nlen-1)-1)/2;
for (int i=index;i>=0;i--)
{
if (2*i+2>=nlen)
{
//只有左儿子
if(p[i]<p[2*i+1])
{
swap(&p[i],&p[2*i+1]);
}
}
else
{
if (p[2*i+1]>=p[2*i+2])
{
if (p[i]<p[2*i+1])
{
swap(&p[i],&p[2*i+1]);
}
}
else
{
if (p[i]<p[2*i+2])
{
swap(&p[i],&p[2*i+2]);
}
}
}
}
}
void adjustHeap(int *p,int nlen,int index)
{
if (nlen<=0||p==NULL)
{
return;
}
if (index*2+1>=nlen) //这是叶子节点
{
return;
}
if (index*2+2>=nlen)//只有左叶子节点
{
if(p[index]<p[2*index+1])
{
swap(&p[index],&p[2*index+1]);
}
}
else
{
if (p[2*index+1]>p[2*index+2])
{
if (p[index]<p[2*index+1])
{
swap(&p[index],&p[2*index+1]);
adjustHeap(p,nlen,2*index+1);
}
}
else
{
if (p[index]<p[2*index+2])
{
swap(&p[index],&p[2*index+2]);
adjustHeap(p,nlen,2*index+2);
}
}
}
}