最大的K个数

原文链接

给定一个N个数的数组arr[N],任意排列,选出其中最大的K个数。


方法1:排序,取后K个数。复杂度: O(NlogN)
方法2:partition,随意选一个数组中的数key,对数组进行划分,返回位置pos,如果pos右侧的数等于K,则结束,如果大于K,则再对从pos到数组尾的子数组进行partition,如果小于K,则对从数组头到pos位置的子数组进行partition,找出剩下的元素。时间复杂度:O(NlogK)
void printarray(int *arr,int beg,int end)
{
    for(int i = end-1; i>=beg-1; --i)
    {
        cout<<arr[i]<<' ';
    }
}

int partition(int *arr,int beg,int end)
{
    if(beg<1||beg>end)
    {
        cout<<"error input"<<'\n';
        exit(0);
    }
    if(beg==end)
        return beg;
    int i = beg-2;
    int j = beg-1;
    int key = arr[end-1];
    while(j<end-1)
    {
        if(arr[j]<=key)
        {
            ++i;
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        ++j;
    }
    int temp = arr[end-1];
    arr[end-1] = arr[++i];
    arr[i] = temp;
    return i+1;
}

void maxK(int *arr,int beg,int end,int K)
{
    if(beg<1||beg>end)
    {
        cout<<"error input"<<'\n';
        exit(0);
    }
    if(end-beg+1==K)
    {
        printarray(arr,beg,end);
        return;
    }
    int mid = partition(arr,beg,end);
    int tmp = end-mid+1;
    if(tmp==K)
        printarray(arr,mid,end);
    else if(tmp<K)
    {
        printarray(arr,mid,end);
        maxK(arr,beg,mid-1,K-tmp);
    }
    else
        maxK(arr,mid+1,end,K);
}

方法3:最小堆,建立一个K元素的最小堆,用arr的前K个元素初始化,然后从arr的第K+1个元素开始扫描数组,如果大于最小堆的根,则互换元素,并对根做minheap_fy,这样最后最小堆里剩的就是最大的K个元素.时间复杂度:O(NlogK)
void minheap_fy(int *heap,int index,int heapsize)
{
    int left = index<<1;
    int right = left + 1;
    int smallest = index;
    if(left<=heapsize&&heap[smallest-1]>heap[left-1])
        smallest = left;
    if(right<=heapsize&&heap[smallest-1]>heap[right-1])
        smallest = right;
    if(smallest != index)
    {
        int temp = heap[index-1];
        heap[index - 1] = heap[smallest-1];
        heap[smallest-1] = temp;
        minheap_fy(heap,smallest,heapsize);
    }
}

void build_minheap(int *heap,int heapsize)
{
    int temp = heapsize/2;
    while(temp>0)
    {
        minheap_fy(heap,temp,heapsize);
        --temp;
    }
}

void maxK2(int *arr,int size,int K)
{
    if(size<K)
    {
        cout<<"error K"<<'\n';
        return;
    }
    int *heap = new int[K];
    for(int i = 0;i<K;++i)
    {
        heap[i] = arr[i];
    }
    build_minheap(heap,K);
    for(int i = K; i<size; ++i)
    {
        if(arr[i]>heap[0])
        {
            heap[0] = arr[i];
            minheap_fy(heap,1,K);
        }
    }
    for(int i = 0;i<K;++i)
        cout<<heap[i]<<' ';
    delete[] heap;
}

方法4:
如果数的波动不大,或者数全为小范围内的整数,可以考虑用桶排序,用空间换时间,直接取出最大的K个元素即可,桶排序的代码见《线性时间排序》,算法复杂度:O(N).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值