【从零单排之微软面试100题系列】05之查找最小的k个元素

原创 2015年07月06日 19:53:42
本题目选自July大神博客系列【微软面试100题】:july大神,该系列我主要用来记录我的学习笔记。

题目描述:输入n个整数,输出其中最小的k个(k<=n)

 

分析思路:(本题亦见于《剑指offer》面试题30)

最简单的思路莫过于先排序,然后输出排序后的前k个数。如果使用快排,时间复杂度是O(nlogn)

除此之外,还有其它解法。

解法1:基于数组的第k个数字来调整,使比第k个数字小的所有数字位于数组左边,比第k个数字大的所有数字位于数组右边。这样调整之后,位于数组中左边的k个数字就是最小的k个数字(但这k个数字不一定是排好序的)。这种方法的时间复杂度是O(n)

书中给的参考代码:

void GetLeastNumbers(int *input, int n, int* output, int k)
{
   if(input == NULL || n <= 0 || k > n || k <= 0)
      return;  
   int start = 0;
   int end = n - 1;
   int index = Partition(intput, n, start, end);
   while(index != k-1)
   {
     if(index > k - 1)
     {
         end = index - 1;
         index = Partition(input, n, start, end);
     }  
     else
     {
         start = index + 1;
         index = Partition(input, n, start, end);
     }
   } 
   for(int i = 0; i < k; ++i)
    output[i] = input[i];
}

//Partition的实现
int Partition(int* data, int nLength, int start, int end)
{
   if(data == NULL || nLength <= 0 || start < 0 || end > nLength - 1 || start > end)
         throw exception("Invalid Input!");
   int index = RandInRange(start,end);//随机生成start到end之间的整数
   Swap(&data[index], &data[end]);    //选择位置index上的值,并将其与end位置上的数交换
   
   int small = start - 1;             //small用来保存比选中的数小的数的位置
   for(index = start; index < end; ++index) 
   {
       if(data[index] < data[end])     
      {
          ++small;                    
          if(small != index)
               Swap(&data[index],&data[small]);  //如果data[index]<data[end],将small位置的数换成比选中的数小的data[index]
      }
   }
   ++small;
   Swap(&data[small], &data[end]);
   return small;
}

解法二:可以先创建一个大小为k的数据容器来存储最小的k个数字,接下来每次从n个数据中读取一个数。如果容器已有数字少于k个,则读取的数据可以直接放入容器之中;否则,找出已有k个数据中的最大数,与当前数据比较之后更新之。可以利用最大堆来实现该容器,因为最大堆的根结点总是最大,而完成删除和插入操作的时间复杂度是O(logk)。
在STL中,set和multiset都是基于红黑树实现的,于是可以利用STL的multiset容器,以下是参考代码:

typedef multiset<int, greater<int> >            intSet;
typedef multiset<int, greater<int> >::iterator  setIterator;
void GetLeastNunmbers(const vector<int>& data, intSet& leastNumbers, int k)
{
    leastNumbers.clear();
    if(k < 1 || data.size() < k)
       return;
    vector<int>::const_iterator iter = data.begin();
    for(; iter != data.end(); ++iter)
      if(leastNumbers.size() < k)
            leasetNumbers.insert(*iter);
      else
      {
         setIterator iterGreatest = leastNumbers.begin();
         if(*iter < *iterGreatest)
         {
              leastNumbers.erase(iterGreatest);
              leastNumbers.insert(*iter);
         }
      }
}


微软经典面试100题系列(部分)

本文整理自:http://blog.csdn.net/v_july_v/article/details/6543438     1. 把二元查找树转变成排序的双向链表     题目: 输入一棵二元查...
  • zhoudaxia
  • zhoudaxia
  • 2014年07月10日 14:29
  • 16416

微软等数据结构+算法面试100题全部答案集锦

1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不能创建任何新的结点,只调整指针的指向。 10 / \ 6 14 / \ ...
  • lipengshiwo
  • lipengshiwo
  • 2016年11月26日 17:28
  • 3398

查找最小的k个元素 【微软面试100题 第五题】

题目要求:   输入n个整数,输出其中最小的k个。   例如:输入1,2,3,4,5,6,7,8这8个数字,则最小的4个数字为1,2,3,4。 参考资料:剑指offer第30题。 ...
  • tractor_man
  • tractor_man
  • 2014年11月04日 11:44
  • 234

(微软面试100题)查找最小的K个元素

问题描述: 输入n个整数,输出其中最小的k个。 例如输入1,2,3,4,5,6,7和8这8个数字, 则最小的4个数字为1,2,3和4。 解题思路: 构建一个K个元素的堆,最终的算法复杂度...
  • huangkangying
  • huangkangying
  • 2013年01月29日 22:06
  • 491

微软等数据结构+算法面试100题全部答案集锦

微软等数据结构+算法面试100题全部答案集锦 作者:July、阿财。 时间:二零一一年十月十三日。 引言      无私分享造就开源的辉煌。      今是二零一一年十月十三...
  • GarfieldEr007
  • GarfieldEr007
  • 2015年10月06日 14:04
  • 5654

微软公司等数据结构+算法面试100题

微软等公司数据结构+算法面试100题(第1-100题)首次完整亮相 注:本文转自July的博客:http://blog.csdn.net/v_july_v/article/details/60572...
  • qq_33290787
  • qq_33290787
  • 2016年07月11日 11:02
  • 835

查找最小的k 个元素

5.查找最小的k 个元素 题目:输入n 个整数,输出其中最小的k 个。 例如输入1,2,3,4,5,6,7 和8 这8 个数字,则最小的4 个数字为1,2,3 和4。 (参考《编程之美》) 看完题目...
  • quietmao
  • quietmao
  • 2015年03月29日 18:58
  • 426

微软等数据结构+算法面试100题全部答案集锦

作者:July、阿财。 时间:二零一一年十月十三日。  引言      无私分享造就开源的辉煌。      今是二零一一年十月十三日,明日14日即是本人刚好开博一周年。在一...
  • idaretobe
  • idaretobe
  • 2015年01月13日 20:50
  • 1852

纯C语言:分治查找第K个最小元素源码

#include void fun(int array[],int low,int high) { int i = low; int j = high; int temp ...
  • u011131296
  • u011131296
  • 2014年01月03日 00:05
  • 1594

微软100题(5) 查找最小的k个元素

题目:输入n个整数,输出其中最小的k个。 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。 方法一:如果可以修改原来数组的元素,则利用快排的partition算法,...
  • liuqing0517
  • liuqing0517
  • 2015年05月19日 21:48
  • 536
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【从零单排之微软面试100题系列】05之查找最小的k个元素
举报原因:
原因补充:

(最多只允许输入30个字)