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

微软面试100题之第五题

2014-04-14 13:03 405 查看
题目:

输入n 个整数,输出其中最小的 k 个。

例如输入 1 , 2 , 3 , 4 , 5 , 6 , 7 ,8 这 8 个数字,则最小的 4 个数字为 1 , 2 , 3 和 4 。

分析:

本题最简单也最容易想到的解决方法就是把输入的n个整数排序了。当然,排序也有好多种方法,是选择排序、插入排序、快速排序还是堆排序?如果是堆排序还要分为是用大根堆还是小根堆?首先,我们当然会选择时间复杂度较低(nlogn)的排序算法了。

再仔细看下题目,题中好像没有要求我们按大小顺序输出其中的最小的k个数!仅仅要求输入这个k个数而已。这就提示我们不必对所有数据进行排序,只需找出这k个最小数而已。是不是选择排序比较合适?只需要O(n*k)就可以找到最小的k个数据。在具体化些,我们只需申请k个大小的数组存储最后的结果,如果数组未填满,我们就直接将输入的元素放入到数组中;如果数组中放满了k个元素,那么我们就需要找到当前数组中最大的元素值与刚输入的整数值比较,如果刚输入的整数值较小,则进行替换,否则继续输入……

查找k个元素数组的最大值时间复杂度为O(k),需要进行n-k次,所以时间复杂度是O(k(n-k)),最后的平均复杂度应该是O(kn)。至于更多的思路当然还有采用具有k个元素的大根堆来实现,具体可以查看July的详细讲解http://blog.csdn.net/v_JULY_v/article/details/6370650

代码如下:

#include<stdlib.h>

#include<stdio.h>

#define SIZE 10 //k=20

void replace(int datas[],int newdata)

{

int i,pos=-1,max=-(2<<31); //-(2<<31)表示的是int32的负极限,因为考虑到数据中有负数。

//先用一个for循环找出数组中的最大数。

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

{

if(max<datas[i])

{

max=datas[i];

pos=i;

}

}

//将新数据同原来数组中的最大数进行比较。

if(newdata<datas[pos])

datas[pos]=newdata;

}

int main()

{

int datas[SIZE]={0};

int k=0,input;

freopen("input.txt","r",stdin); //从input.txt文件中读取数据

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

{

//先从文件中读取SIZE个数据

if(k<SIZE)

{

datas[k++]=input;

}

//接下来对于新读取的数据进行比较和替换(具体做法见上面分析中的第二段)

else

replace(datas,input);

}

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

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

printf("\n");

getchar();

return 0;

}

对于上述代码有些同学会不太懂,最起码我刚开始是这样的



最难懂的就是replace函数,我都以注释介绍了。(PS:所有注释都是本人自己添加的,就是为了像我这样的小白更明白一些



对于此题还有更为详细的解释,参见:http://blog.csdn.net/littlestream9527/article/details/8104731
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: