题目:

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

思路:

1、排序

把输入的n个整数排序,然后取前k个数;

时间复杂度:O(nlogn)

2、Partition

通过partition找到第k大的数,它的左边就是前k小的数;

时间复杂度:O(n)

3、最大堆

构建k个整数的最大堆数据结构,然后将剩余n-k个整数依次与堆顶比较,大则抛弃,小则删除堆顶并插入,最后的最大堆就是最小的k个整数;

堆是基于二叉树来实现的,因此插入和删除操作都在O(logk)时间内完成。在代码中可以通过STL中的容器来实现,如set,multiset,priority_queue等,都是基于红黑树实现的,所以是排序的。

时间复杂度:O(nlogk)

代码:

1、Partition方法

  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. int Partition(int* numbers,int start,int end){
  6. int key=numbers[start];
  7. int i=start;
  8. int j=end;
  9. while(i<j){
  10. while(i<j && numbers[j]>=key)
  11. --j;
  12. if(i<j) numbers[i++]=numbers[j];
  13.  
  14. while(i<j && numbers[i]<=key)
  15. ++i;
  16. if(i<j) numbers[j--]=numbers[i];
  17. }
  18. numbers[i]=key;
  19. return i;
  20. }
  21.  
  22. void GetLeastNumbers(int* input,int n,int* output,int k){
  23. if(input==NULL || output==NULL || k>n || n<=0 || k<=0)
  24. return;
  25. int start=0;
  26. int end=n-1;
  27. int index=Partition(input,start,end);
  28. while(index!=k-1){
  29. if(index>k-1){
  30. end=index-1;
  31. index=Partition(input,start,end);
  32. }
  33. else{
  34. start=index+1;
  35. index=Partition(input,start,end);
  36. }
  37. }
  38.  
  39. for(int i=0;i<k;i++)
  40. output[i]=input[i];
  41. }
  42.  
  43. int main()
  44. {
  45. int A[]={4,5,1,6,2,7,3,8};
  46. int len=sizeof(A)/sizeof(A[0]);
  47. int k=4;
  48. GetLeastNumbers(A,len,A,k);
  49.  
  50. for(int i=0;i<k;i++)
  51. cout<<A[i]<<" ";
  52. cout<<endl;
  53. return 0;
  54. }

2、最大堆/大顶堆

  1. #include <iostream>
  2. #include <set>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. typedef multiset<int,greater<int> > inSet;
  8. typedef multiset<int,greater<int> >::iterator setIterator;
  9.  
  10. void GetLeastNumbers_1(const vector<int> &data,inSet &leastNumbers,unsigned int k){
  11. leastNumbers.clear();
  12.  
  13. if(k<1 || data.size()<k)
  14. return;
  15.  
  16. vector<int>::const_iterator it=data.begin();
  17. for(;it!=data.end();it++){
  18. if(leastNumbers.size()<k)
  19. leastNumbers.insert(*it);
  20. else{
  21. setIterator iterGreatest=leastNumbers.begin();
  22. if(*it<*iterGreatest){
  23. leastNumbers.erase(iterGreatest);
  24. leastNumbers.insert(*it);
  25. }
  26. }
  27. }
  28. }
  29.  
  30. int main()
  31. {
  32. int A[]={4,5,1,6,2,7,3,8};
  33. int len=sizeof(A)/sizeof(A[0]);
  34. int k=4;
  35. vector<int> data(A,A+len);
  36.  
  37. inSet leastNumbers;
  38. GetLeastNumbers_1(data,leastNumbers,k);
  39.  
  40. for(setIterator it=leastNumbers.begin();it!=leastNumbers.end();it++)
  41. cout<<*it<<" ";
  42. cout<<endl;
  43.  
  44. return 0;
  45. }

在线测试OJ:

http://www.nowcoder.com/books/coding-interviews/6a296eb82cf844ca8539b57c23e6e9bf?rp=2

AC代码:

1、Partition方法:

  1. class Solution {
  2. public:
  3. int Partition(vector<int> &data,int start,int end){
  4. int key=data[start];
  5. int i=start;
  6. int j=end;
  7. while(i<j){
  8. while(i<j && data[j]>=key)
  9. j--;
  10. if(i<j)
  11. data[i++]=data[j];
  12. while(i<j && data[i]<=key)
  13. i++;
  14. if(i<j)
  15. data[j--]=data[i];
  16. }
  17. data[i]=key;
  18. return i;
  19. }
  20.  
  21. vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
  22. vector<int> output;
  23. if(k<1 || input.size()<k)
  24. return output;
  25. int start=0;
  26. int end=input.size()-1;
  27. int index=Partition(input,start,end);
  28. while(index!=k-1){
  29. if(index>k-1){
  30. end=index-1;
  31. index=Partition(input,start,end);
  32. }
  33. else{
  34. start=index+1;
  35. index=Partition(input,start,end);
  36. }
  37. }
  38.  
  39. for(int i=0;i<k;i++)
  40. output.push_back(input[i]);
  41.  
  42. return output;
  43. }
  44. };

2、大顶堆:multiset

  1. class Solution {
  2. public:
  3. typedef multiset<int,greater<int> > inSet;
  4. typedef multiset<int,greater<int> >::iterator inSetIterator;
  5. vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
  6. vector<int> output;
  7. if(k<1 || input.size()<k)
  8. return output;
  9.  
  10. inSet LeastNumbers;
  11. for(vector<int>::iterator it=input.begin();it!=input.end();it++){
  12. if(LeastNumbers.size()<k)
  13. LeastNumbers.insert(*it);
  14. else{
  15. inSetIterator greatest=LeastNumbers.begin();
  16. if(*it<*greatest){
  17. LeastNumbers.erase(*greatest);
  18. LeastNumbers.insert(*it);
  19. }
  20. }
  21. }
  22.  
  23. for(inSetIterator it=LeastNumbers.begin();it!=LeastNumbers.end();it++)
  24. output.push_back(*it);
  25.  
  26. return output;
  27. }
  28. };

3、大顶堆:priority_queue

  1. class Solution {
  2. public:
  3. typedef priority_queue<int,vector<int>,less<int> > PQ;
  4. vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
  5. vector<int> output;
  6. if(k<1 || input.size()<k)
  7. return output;
  8.  
  9. PQ LeastNumbers;
  10. for(vector<int>::iterator it=input.begin();it!=input.end();it++){
  11. if(LeastNumbers.size()<k)
  12. LeastNumbers.push(*it);
  13. else{
  14. int greatest=LeastNumbers.top();
  15. if(*it<greatest){
  16. LeastNumbers.pop();
  17. LeastNumbers.push(*it);
  18. }
  19. }
  20. }
  21. while(!LeastNumbers.empty()){
  22. output.push_back(LeastNumbers.top());
  23. LeastNumbers.pop();
  24. }
  25.  
  26. return output;
  27. }
  28. };

(剑指Offer)面试题30:最小的k个数的更多相关文章

  1. 剑指Offer:面试题30——最小的k个数(java实现)

    问题描述: 输入n个整数,找出其中最小的k个数 思路1: 先排序,再取前k个 时间复杂度O(nlogn) 下面给出快排序的代码(基于下面Partition函数的方法) public void Quic ...

  2. 剑指offer 面试题40. 最小的k个数

    O(N)划分法,注意这个方法会改变原数据(函数参数是引用的情况下)!当然也可以再定义一个新容器对其划分 要求前k小的数,只要执行快排划分,每次划分都会把数据分成大小两拨.直到某一次划分的中心点正好在k ...

  3. 剑指Offer - 九度1371 - 最小的K个数

    剑指Offer - 九度1371 - 最小的K个数2013-11-23 15:45 题目描述: 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是 ...

  4. 剑指offer(29)最小的K个数

    题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 题目分析 这题有两种方法来做. 第一种就是基于partition的 ...

  5. 【剑指Offer】29、最小的K个数

      题目描述:   输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4.   解题思路:   本题最直观的解法就是将输入的n个整数排 ...

  6. 剑指offer面试题30:最小的k个数

    一.题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 二.解题思路 1.思路1 首先对数组进行排序,然后取出前k个数 ...

  7. 面试题30.最小的k个数

    题目:输入n个整数,找出其中最小的k个数,例如输入4,5,1,6,2,7,3,8 这8个数字,则最小的四个数字为1,2,3,4, 这道题是典型的TopK问题,剑指Offer提供了两种方法来实现,一种方 ...

  8. 剑指offer——面试题30:包含min函数的栈

    #include"iostream" #include"stdio.h" using namespace std; ; ; template<typena ...

  9. 剑指offer面试题30.包含min函数的栈

    一开始写的垃圾代码,push和pop都是O(N) class Solution { public: vector<int> vec; int min_val=INT_MAX,min_cnt ...

  10. 【剑指Offer面试题】 九度OJ1371:最小的K个数

    题目链接地址: http://ac.jobdu.com/problem.php?pid=1371 题目1371:最小的K个数 时间限制:1 秒内存限制:32 兆特殊判题:否提交:5938解决:1265 ...

随机推荐

  1. POJ 1942 Paths on a Grid

    // n*m 的格子 从左下角走到右上角的种数// 相当于从 n+m 的步数中选 m 步往上走// C(n+m,m) #include <iostream> #include <st ...

  2. 中小型数据库 RMAN CATALOG 备份恢复方案(二)

    中小型数据库呈现的是数据库并发少,数据库容量小,版本功能受限以及N多单实例等特点.尽管如此,数据库的损失程度也会存在零丢失的情形.企业不愿意花太多的钱又要保证数据库的可靠稳定,可是苦煞了我这些搞DB的 ...

  3. MySQL与Oracle 差异比较之一数据类型

    数据类型 编号 ORACLE MYSQL 注释 1 NUMBER int / DECIMAL DECIMAL就是NUMBER(10,2)这样的结构INT就是是NUMBER(10),表示整型:MYSQL ...

  4. jQuery autoComplete 样式

    前提:使用了jQuery-ui 官网:http://jqueryui.com/autocomplete/ /*** autocomplete ***/ .ui-widget-content { bac ...

  5. Creole

    Home           Bisher besucht:    AnzeigenAnhängeInfo           The Creole 1.0 project has been succ ...

  6. windowsphone8.0 iso 下载地址

    中文版http://download.microsoft.com/download/F/5/6/F56AD199-EF12-43C7-8551-C095394D3B32/fulltril30/iso/ ...

  7. Linux makefile教程之隐含规则九[转]

    隐含规则 ———— 在 我们使用Makefile时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的源程序为中间目标文件(Unix下是[.o] 文件,Windows下是[.o ...

  8. 预热buffer pool

    mysqldump -u root db_name table_name> /dev/null select * from ...

  9. Oracle数据库中有关记录个数的查询

    一.查询表中全部的记录个数 可用两种方法,一种是在oracle的系统表中统计,另一种需要写存储过程统计,方法分别如下. 1.系统表中统计: SELECT sum(num_rows) FROM user ...

  10. 关于Cygwin的x-Server的自动运行以及相关脚本修改

    常常需要用到远端服务器的图形工具,如果在windows端没用xserver的话,很多程序无法运行.一个特殊的例子,emacs在没用xserver的时候,是直接在终端中打开的,如果不修改cygwin.b ...