zoukankan      html  css  js  c++  java
  • 面试题30:最小的k个数

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

    4个数字是1、2、3、4。

    解法一:O(N)的算法,只有当可以修改输入的数组时可以用

    参考面试题29“数组中出现次数超过一半的数字”,同样用partition函数来解决这个问题。如果partition函数的返回值

    为k-1,则说明最左边的k个数就是最小的k个数。

    解法二:O(NlogK)的算法,特别适合处理海量数据

    创建一个大小为k的数据容器来存储最小的k个数字。每次从输入的n个整数中读入一个数,如果容器未满,则将它插入到存放k个数字的容器中。如果容器已满,并且当前数字小于容器中的最大数字,则将容器中的最大数字删除并插入当前数字。如果容器已满,并且当前数字大于容器中的最大数字,则抛弃当前数字。

    因此,当容器满了之后,我们要做3件事情:

    1.在k个整数中找到最大数;

    2.有可能在这个容器中删除最大数;

    3.有可能要插入一个新的数字;

    如果用一个二叉树来实现这个数据容器,那么总能在O(logk)中实现这三步操作。因此总的时间复杂度为O(NlogK)。

    我们可以选择不同的二叉树来实现这个数据容器,最大堆实现较为复杂,因此这里可以选择红黑树。STL中set和multiset都是基于红黑树实现的。考虑到可能有重复的数字,这里采用multiset实现。

     1 typedef multiset<int, greater<int> > intSet;
     2 
     3 typedef multiset<int, greater<int> > ::iterator setIterator;
     4 
     5 void getLeastNumbers(const vector<int>&data, intSet& leastNumbers, int k)
     6 
     7 {
     8   leastNumbers.clear();
     9   if(k<1 || data.size()<k)
    10     return;
    11   vector<int>::const_iterator iter = data.begin();
    12   for (; iter != data.end(); ++iter)
    13   {
    14     if ((leastNumbers.size()) < k)
    15      leastNumbers.insert(*iter);
    16     else
    17     {
    18       setIterator iterGreatest = leastNumbers.begin();
    19       if (*iter < *(leastNumbers.begin()))
    20       {
    21         leastNumbers.erase(iterGreatest));
    22         leastNumbers.insert(*iter);
    23       }
    24     }
    25   }
    26 }

    第二种解法虽然相对第一种解法要慢,但它有两个明显的优点:1.没有修改输入的数据;2.适合海量数据的输入。如果要求从海量数据中找出最小的k个数,由于内存有限,不能将海量数据一次性读入内存,这时可以从辅助存储空间(如硬盘)一次读取一个数据进行处理。

    解法三:利用multiset实现,时间复杂度和空间复杂度都为O(N) 

     1 vector<int> getLeastNumbers(vector<int>&data, int k)
     2  {
     3     int n = data.size();
     4     vector<int>result;
     5     if (k<1 || n==0 || k > n)
     6       return result;
     7     multiset<int>m;
     8     for (int i = 0; i < n; ++i)
     9     {
    10     m.insert(data[i]);
    11     }
    12    multiset<int>::iterator it = m.begin();
    13    for (int i = 0; i < k; ++i)
    14    {
    15      result.push_back(*it);
    16       it++;
    18    }
    19   return result;
    20  }

     

  • 相关阅读:
    Dumpbin 工具的使用
    ffmpeg Windows下采集摄像头一帧数据,并保存为bmp图片
    directdraw显示yuv视频,出现屏保时,yuv显示不出来,表面丢失
    DirectX截图黑屏的解决办法
    VS2008 Project : error PRJ0019: 某个工具从以下位置返回了错误代码: "正在执行生成后事件..."解决方案
    RoundingMode 几个参数详解
    IDEA导入eclipse项目并部署运行完整步骤(转发)
    Intellij idea操作maven时控制台中文乱码
    java 替换json字符串中间的引号保留两边的引号,避免json校验失败
    分布式ID解决方案
  • 原文地址:https://www.cnblogs.com/happygirl-zjj/p/4621808.html
Copyright © 2011-2022 走看看