您的位置:首页 > 职场人生

面试100题:5.查找最小的k个元素

2014-04-22 17:51 495 查看
题目:

输入n个整数,输出其中最小的k个。例如输入1,2,3,4,5,6,7,8和4这几个数字,则最小的4个数字为1,2,3和4。

解一:

/*Title: 5.求n个数中最小的k个:解一

Author: gocode

Date: 2012-10-03*/

#include<iostream>

using namespace std;

class MinK

{

private:

void shiftDown(int *ret,int pos,int length)

{

int t=ret[pos];

for(int s=2*pos+1;s<=length;s=2*s+1)

{

if(s<length&&ret[s]<ret[s+1])

++s;

if(t<ret[s])

{

ret[pos]=ret[s];

pos=s;

}

else break;

}

ret[pos]=t;

}

int *array;

int size;

public:

MinK(int *arr,int si):array(arr),size(si){}

bool kmin(int k,int*& ret)

{

if(k>size)

{

ret=NULL;

return false;

}

else

{

ret=new int[k--];

int i;

for(i=0;i<=k;++i)

ret[i]=array[i];

for(int j=(k-1)/2;j>=0;--j)

shiftDown(ret,j,k);

for(;i<size;++i)

if(array[i]<ret[0])

{

ret[0]=array[i];

shiftDown(ret,0,k);

}

return true;

}

}

void remove(int*& ret)

{

delete[] ret;

ret=NULL;

}

};

int main()

{

int array[]={1,2,3,4,5,6,7,8};

MinK mink(array,sizeof(array)/sizeof(array[0]));

int *ret;

int k=4;

if(mink.kmin(k,ret))

{

for(int i=0;i<k;++i)

cout<<ret[i]<<" ";

cout<<endl;

mink.remove(ret);

}

system("pause");

return 0;

}

解二:

思路:利用make_heap选出vector前K个数的最大值,对于后面的元素,与最大值作比较,如果小于最大值,则替换最大值,然后再次make_heap,选出当前k个数中的最大值。此种解法利用STL函数跳过了建堆过程。make_heap是标准算法库里的模板函数,用于将存储在vector/deque中的元素进行堆操作,将[start, end)范围进行堆排序,默认使用less<int>, 即最大元素放在第一个,也即大根堆

/*Title: 5.求n个数中最小的k个:解二-最大堆

Author: gocode

Date: 2012-10-03*/

#include <iostream>

#include <vector>

#include <algorithm> // 用于使用make_heap()和sort()

using namespace std;

// 利用make_heap()函数创建最大根堆,这样0-K个数中得最大值被保留在数组的第一个位置

// 然后让数组的第一个值和N-K之后的数组值比较,发现小的就替换

// 并重新构建最大根堆,永远保持数组第一个值是堆中最大,直到替换完

void find(vector<int> &a, int k)

{

if(a.size() < k)

return;

// 构建最大根的堆结构

make_heap(a.begin(), a.begin() + k);

// 将堆中的最大值替换为k之后的小值,然后重新构建堆

for(vector<int>::size_type i = k; i != a.size(); i++)

{

if(a[i] < a[0])

{

a[0] = a[i];

make_heap(a.begin(), a.begin() + k);

}

}

// 从小到大排序

sort(a.begin(), a.begin() + k);

// 打印

for(vector<int>::size_type i = 0; i != k; i++)

cout<<a[i]<<" ";

}

int main()

{

vector<int> a;

for(int j = 8; j > 0; j--)

a.push_back(j);

find(a, 4);

system("pause");

return 0;

}

解三:

每次循环求出数组0-K个数的最大值max,然后和N-K个值比较,把小的值赋给max。

参考:http://xingyunbaijunwei.blog.163.com/blog/static/7653806720122293850244/

/*Title: 5.求n个数中最小的k个:解三-数组

Author: gocode

Date: 2012-10-03*/

#include<stdlib.h>

#include<stdio.h>

#define K 4 // K个最小值

#define N 10 // 数组容量

// 求当前datas[0]...datas[K]数组里的最大值

// 并与N-K个值newdata做比较

// 如max小于datas[N-K],则交换

void replace(int datas[], int newdata)

{

int i, pos = -1, max = -(2<<31);

for(i = 0; i < K; i++)

{

if(max < datas[i])

{

max = datas[i];

pos = i;

}

}

if(newdata < datas[pos])

datas[pos] = newdata;

}

void main()

{

int datas[K] = {0};

int j = 0, input;

// 这里的input.txt位置是相对于*.cpp文件的

// freopen会把文件里的内容读入到stdin中

freopen("Debug\\input.txt","r",stdin);

// 这里的scanf会把上面stdin里的内容赋值给input

// EOF表示流末尾

while(EOF != scanf("%d", &input))

{

if(j < K)

datas[j++] = input;

else

replace(datas, input);

}

printf("List array:\n");

for(j = 0; j < K; j++)

printf("%d ",datas[j]);

fclose(stdin);

system("pause"); // 使程序暂停,可以看console的结果

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: