查找最小的K个数

11 篇文章 0 订阅

输出最小的K个数
方案1:如果输入的数组可变,我们可以借助Partion部分排序的思想,随机选k值,经过排序后,k左边的数都比k小,k右边的数都比k大,这样经过排序后,在k左边的数字就是最小的K个数:

int Partion(int*a, int n, int left, int right)
{
    if (a == NULL || n <= 0)
    {
        return 0;
    }
    if(left >= right)
    {
        return 0;
    }
    int key = a[right];
    while (left < right)
    {
        if (left < right&&a[left] <= key)
        {
            ++left;
        }
        a[right] = a[left];
        if (left < right&&a[left] >= key)
        {
            --right;
        }
        a[right] = a[left];
    }
    a[left] = key;
    return left;
}
void GetlastNums(int*Input, int n, int *Out, int k)
{
    if (Input == NULL || Out == NULL || n < k)
    {
        return;
    }
    int begin = 0;
    int end = n - 1;
    int index = Partion(Input, n, begin, end);
    while(index!=k-1)
    {
        if (index>k - 1)
        {
            //最小的k个数在中位数左边
            end = index - 1;
            index = Partion(Input, n, begin, end);
        }
        else
        {
            //最小的K个数在中位数的右边
            begin = index + 1;
            index = Partion(Input, n, begin, end);

    }
    for (int i = 0; i < k; i++)
        Out[i] = Input[i];
}

但是方案一有明显的限制:我们需要修改输入的数组,因为,Partion会改变数组的数字的顺序,如果不修改数组的顺序该如何呢?
方案二:适合海量数据的处理
我们先建一个大小为K个元素数据的容器用来存储最小的K个数,接下来每次从输出的n个数据的整数中读取一个数,如果容器里面的元素的个数小于k,直接将输出的元素插入到容器里面,如果容器里面的元素个数已经是k,表明容器已经满了,此时比较下一个插入的数字与容器的元素的最大值比较,小,用这个数字替换容器中的最大的元素,如果大,直接抛弃,直到输入的元素全部插入容器

我们发现容器满了会做三件事:一是在k个整数中找最大的数,二是有可能在这个容器中删除最大的数,三:可能要插入一个新的数字
这时我们很容易想到大堆,堆顶是最大元素,其他的元素都比堆顶要小,取堆顶的元素时间复杂度是O(1),堆的插入和删除时间复杂度nlgn,如果用二叉树来做总的效率就是nlgK
但是有个缺点就是插入和删除都要重新调整堆

我们想到了红黑树,红黑树的插入,查找,删除的效率都是lgn
在STL中set和multiset都是基于红黑树实现

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include <functional>
using namespace std;
typedef multiset<int, std::greater<int>> inset;
typedef multiset<int, std::greater<int>> ::iterator setiter;

void _GetleaseNum(vector<int>&data, inset&Leasenum, int k)
{

    if (data.size() < k || k < 1)
    {
        return;
    }
    vector<int>::iterator it = data.begin();//迭代器遍历输入的数组
    for (; it < data.end(); it++)
    {
        if (Leasenum.size() < k)
        {
            //当容器里面的元素小于k时
            Leasenum.insert(*it);
        }
        else
        {
            //此时容器已经满了
            setiter itrgreater = Leasenum.begin();//找到容器里面最大的元素
            if (*Leasenum.begin()>(*it))
            {
                Leasenum.erase(itrgreater);//删除最大的元素
                Leasenum.insert(*it);//然后插入
            }
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值