查找最小的k个元素

题目:

输入n 个整数,输出其中最小的 k 个。
例如输入 1 , 2 , 3 , 4 , 5 , 6 , 7 ,8 这 8 个数字,则最小的 4 个数字为 1 , 2 , 3 和 4 。

分析:

        本题最简单也最容易想到的解决方法就是把输入的n个整数排序了。当然,排序也有好多种方法,是选择排序、插入排序、快速排序还是堆排序?如果是堆排序还要分为是用大根堆还是小根堆?首先,我们当然会选择时间复杂度较低(nlogn)的排序算法了。

         再仔细看下题目,题中好像没有要求我们按大小顺序输出其中的最小的k个数!仅仅要求输入这个k个数而已。这就提示我们不必对所有数据进行排序,只需找出这k个最小数而已。是不是选择排序比较合适?只需要O(n*k)就可以找到最小的k个数据。在具体化些,我们只需申请k个大小的数组存储最后的结果,如果数组未填满,我们就直接将输入的元素放入到数组中;如果数组中放满了k个元素,那么我们就需要找到当前数组中最大的元素值与刚输入的整数值比较,如果刚输入的整数值较小,则进行替换,否则继续输入……

        查找k个元素数组的最大值时间复杂度为O(k),需要进行n-k次,所以时间复杂度是O(k(n-k)),最后的平均复杂度应该是O(kn)。至于更多的思路当然还有采用具有k个元素的大根堆来实现,具体可以查看July的详细讲解http://blog.csdn.net/v_JULY_v/article/details/6370650

        代码如下:

#include<stdlib.h>
#include<stdio.h>
#define SIZE 10  //k=20
void replace(int datas[],int newdata)
{
 int i,pos=-1,max=-(2<<31);
 for(i=0;i<SIZE;i++)
 {
  if(max<datas[i])
  {
   max=datas[i];
   pos=i;
  }
 }
 if(newdata<datas[pos])
  datas[pos]=newdata;
}
int main()
{
 int datas[SIZE]={0};
 int k=0,input;

 freopen("input.txt","r",stdin); 
     
 while(EOF!=scanf("%d",&input)) 
 {
  if(k<SIZE)
  {
   datas[k++]=input;
  }
  else
   replace(datas,input);
 }
    
 for(k=0;k<SIZE;k++)
  printf("%d ",datas[k]);
 printf("\n");

 getchar();
 return 0;
}

下面的方法则是采用STL中multiset来实现的。来自于http://zhedahht.blog.163.com/blog/static/2541117420072432136859/:

typedef multiset<int, greater<int> >  IntHeap;
///
// find k least numbers in a vector
///

void FindKLeastNumbers(const vector<int>& data,IntHeap&leastNumbers,unsigned k)                            
{
      leastNumbers.clear();

      if(k == 0 || data.size() < k)
            return;

      vector<int>::const_iterator iter = data.begin();
      for(; iter != data.end(); ++ iter)
      {
            // if less than k numbers was inserted into leastNumbers
            if((leastNumbers.size()) < k)
                  leastNumbers.insert(*iter);

            // leastNumbers contains k numbers and it's full now
            else
            {
                  // first number in leastNumbers is the greatest one
                  IntHeap::iterator iterFirst = leastNumbers.begin();

                  // if is less than the previous greatest number 
                  if(*iter < *(leastNumbers.begin()))
                  {
                        // replace the previous greatest number
                        leastNumbers.erase(iterFirst);
                        leastNumbers.insert(*iter);
                  }
            }
      }
}

转载于:https://www.cnblogs.com/liuyubloch/archive/2012/08/24/2654262.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值