题目:

输入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方法

#include <iostream>

using namespace std;

int Partition(int* numbers,int start,int end){
int key=numbers[start];
int i=start;
int j=end;
while(i<j){
while(i<j && numbers[j]>=key)
--j;
if(i<j) numbers[i++]=numbers[j]; while(i<j && numbers[i]<=key)
++i;
if(i<j) numbers[j--]=numbers[i];
}
numbers[i]=key;
return i;
} void GetLeastNumbers(int* input,int n,int* output,int k){
if(input==NULL || output==NULL || k>n || n<=0 || k<=0)
return;
int start=0;
int end=n-1;
int index=Partition(input,start,end);
while(index!=k-1){
if(index>k-1){
end=index-1;
index=Partition(input,start,end);
}
else{
start=index+1;
index=Partition(input,start,end);
}
} for(int i=0;i<k;i++)
output[i]=input[i];
} int main()
{
int A[]={4,5,1,6,2,7,3,8};
int len=sizeof(A)/sizeof(A[0]);
int k=4;
GetLeastNumbers(A,len,A,k); for(int i=0;i<k;i++)
cout<<A[i]<<" ";
cout<<endl;
return 0;
}

2、最大堆/大顶堆

#include <iostream>
#include <set>
#include <vector> using namespace std; typedef multiset<int,greater<int> > inSet;
typedef multiset<int,greater<int> >::iterator setIterator; void GetLeastNumbers_1(const vector<int> &data,inSet &leastNumbers,unsigned int k){
leastNumbers.clear(); if(k<1 || data.size()<k)
return; vector<int>::const_iterator it=data.begin();
for(;it!=data.end();it++){
if(leastNumbers.size()<k)
leastNumbers.insert(*it);
else{
setIterator iterGreatest=leastNumbers.begin();
if(*it<*iterGreatest){
leastNumbers.erase(iterGreatest);
leastNumbers.insert(*it);
}
}
}
} int main()
{
int A[]={4,5,1,6,2,7,3,8};
int len=sizeof(A)/sizeof(A[0]);
int k=4;
vector<int> data(A,A+len); inSet leastNumbers;
GetLeastNumbers_1(data,leastNumbers,k); for(setIterator it=leastNumbers.begin();it!=leastNumbers.end();it++)
cout<<*it<<" ";
cout<<endl; return 0;
}

在线测试OJ:

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

AC代码:

1、Partition方法:

class Solution {
public:
int Partition(vector<int> &data,int start,int end){
int key=data[start];
int i=start;
int j=end;
while(i<j){
while(i<j && data[j]>=key)
j--;
if(i<j)
data[i++]=data[j];
while(i<j && data[i]<=key)
i++;
if(i<j)
data[j--]=data[i];
}
data[i]=key;
return i;
} vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> output;
if(k<1 || input.size()<k)
return output;
int start=0;
int end=input.size()-1;
int index=Partition(input,start,end);
while(index!=k-1){
if(index>k-1){
end=index-1;
index=Partition(input,start,end);
}
else{
start=index+1;
index=Partition(input,start,end);
}
} for(int i=0;i<k;i++)
output.push_back(input[i]); return output;
}
};

2、大顶堆:multiset

class Solution {
public:
typedef multiset<int,greater<int> > inSet;
typedef multiset<int,greater<int> >::iterator inSetIterator;
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> output;
if(k<1 || input.size()<k)
return output; inSet LeastNumbers;
for(vector<int>::iterator it=input.begin();it!=input.end();it++){
if(LeastNumbers.size()<k)
LeastNumbers.insert(*it);
else{
inSetIterator greatest=LeastNumbers.begin();
if(*it<*greatest){
LeastNumbers.erase(*greatest);
LeastNumbers.insert(*it);
}
}
} for(inSetIterator it=LeastNumbers.begin();it!=LeastNumbers.end();it++)
output.push_back(*it); return output;
}
};

3、大顶堆:priority_queue

class Solution {
public:
typedef priority_queue<int,vector<int>,less<int> > PQ;
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> output;
if(k<1 || input.size()<k)
return output; PQ LeastNumbers;
for(vector<int>::iterator it=input.begin();it!=input.end();it++){
if(LeastNumbers.size()<k)
LeastNumbers.push(*it);
else{
int greatest=LeastNumbers.top();
if(*it<greatest){
LeastNumbers.pop();
LeastNumbers.push(*it);
}
}
}
while(!LeastNumbers.empty()){
output.push_back(LeastNumbers.top());
LeastNumbers.pop();
} return output;
}
};

(剑指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. JNDI绑定数据库

    经过3个多小时的努力,配置JNDI数据源(主要是通过DBCP连接池)终于搞定- 还是Tomcat官方的说明好,不过全是英文的,大概还看得懂. 百度上那么花花绿绿的太多了,一个也没成功!... 本例使用 ...

  2. Python定时调度--多任务同一时间开始跑 scheduler.enterabs

    Event Priorities If more than one event is scheduled for the same time their priority values are use ...

  3. spring TaskExecutor

    TaskExecutor抽象 Spring 2.0 为执行器(Executor)处理引入了一个新的抽象层.Executor是Java 5的名词,用来表示线程池的概念.之所以用这个奇怪的名词,是因为实际 ...

  4. WINHEX 使用教程

    Winhex有完善的分区管理功能和文件管理功能,能自动分析分区链和文件簇链,能对硬盘进行不同方式不同程度的备份,甚至克隆整个硬盘:它能够编 辑任何一种文件类型的二进制内容(用十六进制显示)其磁盘编辑器 ...

  5. Oracle数据泵

    要使用数据泵必须先创建数据库目录        数据库目录只允许sys创建        普通用户使用 必须授权 假设scott 用户是导出导入用户 SQL> ! mkdir dp_dir SQ ...

  6. VMware 命令行下安装以及导入Ubuntu系统

    前提: 鉴于个人PC性能太弱,考虑是否可以将在PC上搭建好的环境移植到高性能服务器上.想到后就干呗. 下载完对应操作系统的安装包后按如下步骤操作: 安装包名称:VMware-Workstation-F ...

  7. iOS学习笔记之回调(一)

    什么是回调 看了好多关于回调的解释的资料,一开始总觉得这个概念理解起来有点困难,可能是因为自己很少遇到这种类型的调用吧.探索良久之后,才算有点启发,下面是自己的一点理解. 我们知道,在OSI网络七层模 ...

  8. NewtonPrincipia --- 公理或运动的定律 --- 系理二

    NewtonPrincipia --- 公理或运动的定律 --- 系理二 自然哲学的数学原理>公理或运动的定律>系理II 平行四边形ABCD,那么:直接的力AD由任意的力AB和BD合成,直 ...

  9. ansible安装及问题解决

    本文主要用来安装ansible,在进行安装的时候,也可以使用其他的版本进行安装,本文主要讲述安装ansible的步骤,还有常用问题的解决. 1.查看python版本 由此可以看到python的版本为2 ...

  10. sqoop 初用

    http://blog.csdn.net/dbanote/article/details/8907650 目前版本的Sqoop中,使用自由形式查询导入,只提供简单的查询,没有复杂的和“OR”条件查询在 ...