微软面试题系列(五):查找最小的 k 个元素

    好了,断续微软面试题的学习!看到题目,我首先想到的是树状数组,后来看PPT才发现用树状数组可以实现查找第k大的元素,细想一下和这道题也差不多。网上的很多实现都是用堆做的,用堆大多数也是用C++的STL,Multiset来实现。网上代码很多,而且我也没弄明白这题,先就不自己写代码了。

    在这里,给出一个O(n)复杂度的实现:BFPRT算法。我也是才看到的,觉得很好,就先保存下来。申明一下,暂时用的是别人的代码.

    关于BFPRT算法,可以参考下面的链接:

http://zhulinb123.blog.163.com/blog/static/184414043201110111611859/

 http://ds.fzu.edu.cn/fine/resources/FlashContent.asp?id=82

   第二个链接是一个flash动画,做得非常好!能让人很清晰地看到这个算法的执行过程。好了,还是把代码贴出来吧!

 

 
 
  1. /* 
  2.  * Problem_5.cpp 
  3.  *寻找最小的K个数 
  4.  *  Created on: 2012-8-29 
  5.  *      Author: Administrator 
  6.  */ 
  7. #include<iostream.h> 
  8. #include<stdlib.h> 
  9. #include<time.h> 
  10. #define MAX_VALUE 10000 
  11. #define random() rand()%MAX_VALUE 
  12. #define N 10 
  13. int a[N]; 
  14. class Find{ 
  15. public
  16.     void bubble(int first,int end) //冒泡排序 
  17.     { 
  18.         for(int flag=first;flag<end;flag++) 
  19.             for(int i=end;i>flag;i--) 
  20.                 if(a[i]<a[i-1]) 
  21.                 { int t=a[i]; 
  22.                     a[i]=a[i-1]; 
  23.                     a[i-1]=t; 
  24.                 } 
  25.     } 
  26.     int partition(int p,int r,int x) //数组a中从a[p]到a[r]的元素按照x划分,大于x的在左边,小于x的在右边 
  27.     { 
  28.         int i,j; 
  29.         for(i=p,j=r;i<j;i++) 
  30.         { 
  31.             if(a[i]>x) 
  32.             { 
  33.                 while(i<j&&a[j]>x) 
  34.                     j--; 
  35.                 if(i!=j){ 
  36.                     int t=a[i]; 
  37.                     a[i]=a[j]; 
  38.                     a[j]=t; 
  39.                     j--; 
  40.                 } 
  41.             } 
  42.         } 
  43.         return i-1; 
  44.     } 
  45.     int select(int p,int r,int k) //寻找中位数 
  46.     {   int i; 
  47.         if(r-p<5){ 
  48.         bubble(p,r); 
  49.         return a[p+k-1]; 
  50.         } 
  51.         for(i=0;i<(r-p-4)/5;i++) 
  52.         { 
  53.             int s=p+5*i,t=s+4; 
  54.             bubble(s,t); 
  55.             int temp=a[p+i]; 
  56.             a[p+i]=a[s+2]; 
  57.             a[s+2]=temp; 
  58.         } 
  59.         int x=select(p,p+(r-p-4)/5,(r-p+6)/10); 
  60.         i=partition(p,r,x); 
  61.         int j=i-p+1; 
  62.         if(k<=j) 
  63.             return select(p,i,k); 
  64.         else 
  65.             return select(i+1,r,k-j); 
  66.         } 
  67. }; 
  68. int main() 
  69. //  clock_t start,end; 
  70. //  double elapsed; 
  71. //  srand((int)time(NULL)); 
  72.     for(int k=0;k<N;k++){ 
  73.         a[k]=random(); 
  74.         cout<<a[k]<<"\t"
  75.     } 
  76.     cout<<endl; 
  77. //  start=clock(); 
  78.     Find f; 
  79.     int n=4; 
  80.     cout<<"The No."<<n<<" is :"<<f.select(0,N-1,n)<<endl; 
  81. //  end=clock(); 
  82. //  elapsed=((double)(end-start));//CLOCKS_PER_SEC; 
  83. //  cout<<"Time: "<<elapsed<<endl; 
  84.     cout<<"最小的"<<n<<"个元素为:"<<endl; 
  85.     for(int k=0;k<n;k++){ 
  86.         cout<<a[k]<<"\t"
  87.     } 
  88.     return 0; 
  89.  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值