剑指offer:最小的k个数(topk问题)

原题链接: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);
        }
    }

最后返回这个数组就可以了。这个算法的时间复杂度相对较小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值