原题链接:https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof/description/
看到这个题的第一眼是不是想直接排序?但是一般排序的时间复杂度都是o(n²),想到堆排序时时间复杂度也有o(n*logn),还有一种办法就是制造一个N个数的堆每次pop一下堆顶的数据,这个的时间复杂度是o(n*logk),这个的时间复杂度也很高。在这里我们用一种时间复杂度相对较低的只有o(k*logn)。
在这里要先建立一个为大小k的堆
void swap(int* e1,int*e2)
{
int tmp = *e1;
*e1 = *e2;
*e2 = tmp;
}
void AdjustDown(int* arr,int n, int root)//向下调整函数
{
int parent = root;
int child = 2*parent+1;
while(child<n)
{
if(child+1<n && arr[child]<arr[child+1])
{
child++;
}
if(arr[child]>arr[parent])
{
swap(&arr[child],&arr[parent]);//交换
parent = child;
child = 2*parent+1;
}
else
{
break;
}
}
}
for(int i = 0;i<k;i++)
{
returnarr[i] = arr[i];
}
//建立大堆
for(int i = (k-1-1)/2;i>=0;i--)
{
AdjustDown(returnarr,k,i);
}
当要求最小的数的话我们建立的大堆堆顶就是下面k个数的最大值,如果外面还有比堆顶小的数就可以进来,在进行一次向下调整,在组件成堆。
for(int j = k;j<arrSize;j++)
{
if(arr[j]<returnarr[0])
{
swap(&arr[j],&returnarr[0]);
AdjustDown(returnarr, k,0);
}
}
最后返回这个数组就可以了。这个算法的时间复杂度相对较小。