微软面试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
输入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
相关文章推荐
- 查找最小的k个元素 【微软面试100题 第五题】
- 微软等数据结构与算法面试100题 第五题
- 查找最小的k个元素 【微软面试100题 第五题】
- 横空出世,席卷互联网--评微软等公司数据结构和算法面试100题
- 永久勘误:微软等面试100题答案V0.3版[第21-40题答案]
- 微软等数据结构+算法面试100题014
- 微软等数据结构+算法面试100题解答018
- 全新整理:微软、谷歌、百度等公司经典面试100题[第101-160题]
- 微软、谷歌、百度等公司经典面试100题[第1-60题]——自己的实现
- July 微软面试100题 第11题 求二叉树的最大距离
- 永久优化:微软技术面试100题第11-20题答案修正与优化
- 微软等数据结构+算法面试100题(3)--怎样把一个链表掉个顺序(也就是反序,注意链表的边界条件并考虑空链表)?
- 微软等数据结构+算法面试100题(10)--三道面试题
- 微软等数据结构+算法面试100题(27)--颠倒栈
- 微软等数据结构+算法面试100题(39)-- 左旋数组中查找
- 微软面试100题 之24栈的push、pop序列
- 精选微软等公司经典的算法面试100题
- [微软面试100题] 设计包含min函数的栈
- 微软面试100题
- 微软面试100题