面試雜題(一)數組中最小的k個數

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


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章