要找到數組中最小的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);
}
}
}
}