百度笔试题-从20数组内取出最大的500个
来源:互联网 发布:wifi网络突然变得很差 编辑:程序博客网 时间:2024/05/17 23:28
题干
20个有序数组,每个数组有500个数字,取出这10000个数字中最大的500个,怎么做?
我的做法
- 蛮力法:将这个10000个数组,放入一个数组内,然后排序,取出前500个。
- 写一个方法,将两个数组,将两个数组整合到一个数组里面,排序,前500个就是我们需要的,再反复调用这个方法。具体来说:有一个MAX先装满0,然后它先与A[1]装在一个1000的数组内后,排序,把前500个再复制给Max,然后再让MAX与A[2]重复上述过程,一直到A[19];
2个方法都很蠢。最好的做法:
见:http://zhidao.baidu.com/link?url=KU9AwrgsUsCXWMO7oOLTpt6WW58dHZRfQ36wyxsBYwdeSF07C-Pe6sjkrKwQnyGDoYUe_9QD9PKlu0bSGS9LPK
再用自己的话叙述一遍:
先作一个结构体:结构体内2个元素,一个是具体的数值,另一个是这个数值的来源。
然后从20个数组,分别取出最大的一个数,以结构体的形式,放入一个大小为20的数组。
对这个大小为20的数组进行排序(实际上这里如果使用最大堆的话,是不一定非要排序的,只需要完成建立最大堆的过程即可,当建立的完成最大堆后,最大元素就是需要被取走的元素,所以每次只需要调整一次堆即可,取出最大的一个数,放入大小为500的集合(这个集合装有最终的结果)。
从被取走的那个数的数值来源,再从那个数组取一个数,放入大小为20的数组。
重复上述过程。
最后集合内放有500个最大的数。
对于其中的排序,根据排序的时间复杂度,归并和堆排序都不错。
我自己手算试了一下,确实堆排序要更快一些。有时堆只有一步就可把最大值算出,归并要2步。
个人觉得这里用堆还是归并都不是重点了。
另外,需要记一下各类排序的时间复杂度和空间复杂度:
来自:http://en.wikipedia.org/wiki/Sorting_algorithm
上述标准答案的时间复杂度就是:519*log(2)20。我认为就是519乘以log以2为底的20.
因为,在最坏的情况下,每次要移动log(2)20个元素,从堆的最下面弄到最上面。一共要移动519次。当集合中有499个元素的时候,大小为20的数组必然要有20个,才能选出最后一个,所以一共进行了519次。
再看看我的2个算法的时间复杂度:
第一种:其实是看排序,我对一个n=10000的数组进行了排序,最好也是10000*log(2)10000,将20个数组的值赋值给10000的数组,我都不加了。
第二种:我对大小规模为1000的数组进行了排序10次,也就是10*1000*log(2)1000。比1还有点好一点
不过都没把握到解体的本质。
下面是我完成的源代码,标准答案主要在思路,我就没有写源码了。两种排序的输出结果一样的。
#include <stdlib.h>#include <stdio.h>#include <algorithm>int i,j,x;int A[20][500];int MAX[500];/*解法一,把这个20个数组放到一个数组内,再一降序排序,前500个就是最大的。这是个很没有水平的办法,要是让我找出10000000000000000000000个数的前5个,难道我还要遍历?但貌似不遍历也没有办法啊*/void solutionOne(){int a[10000];x=0;for(i=0;i<20;i++){for(j=0;j<500;j++){a[x]=A[i][j];x++;}}std::sort(a,a+10000);for(j=9999;j>9499;j--){printf("-%d-",a[j]);}}/*这个是qsort函数需要函数,用来区别升序还是降序,我们这里是降序*/int comp ( const void *a, const void *b ){ return *(int *)b-*(int *)a;//这样表示降序排列}void findMax500(int m){int temp[1000];x=0;for(j=0;j<500;j++){temp[x]=MAX[j];x++;}for(j=0;j<500;j++){temp[x]=A[m][j];x++;}qsort(temp,1000,sizeof(int),comp);for(j=0;j<500;j++){MAX[j]=temp[j];}}void main(){//创建数组并赋值for(i=0;i<20;i++){for(j=0;j<500;j++){A[i][j]=rand()%100000+1;}}//对每个数组排序,达到题目要求for(i=0;i<20;i++){std::sort(A[i],A[i]+500);}//打印其中某一个,看看是不是已经排好序了/*for(j=0;j<500;j++){printf("%d-",A[5][j]);}*//*现在已经完成了题设的要求*//*解法二:写一个方法,将两个数组,将两个数组整合到一个数组里面,排序,前500个就是我们需要的,再反复调用这个方法。有一个MAX先装满0,然后它先与A[1]装在一个1000的数组内后,排序,把前500个再复制给Max,然后再让MAX与A[2]重复上述过程,一直到A[19];*/for(j=0;j<500;j++){//初始化数组MAX,使其全为0MAX[j]=0;}for(i=0;i<20;i++){findMax500(i);}for(j=0;j<500;j++){printf("+%d+",MAX[j]);//打印出来后与solutionOne对比}solutionOne();system("pause");}
- 百度笔试题-从20数组内取出最大的500个
- 从数组中取出n个元素的组合
- 算法题-从包含n个元素的无序列表中取出和最大的连续子集
- 假定有20个 有序 数组,每个数组有500个数字,数字类型32位uint数值,现在需要取出这10000个数字中最大的500个,怎么做?
- php取出数组内指定的值
- 百度的一道笔试题:N个从大到小排好序的整型队列,求top M元素
- 求一维数组中不重叠的两个子数组的最大和(百度2014年笔试题)
- 一道笔试题:从1亿个整数中找出最大的一万个
- 从一个数组中随机的取出若干个不同的数
- 从数组中取出不同的元素
- Company BDui 面试 笔试 : 从10个已按从大到小排列好的数组中,求top 15个最大的数
- 从数组中取出n个元素的所有组合(递归实现)
- 从数组中取出n个元素的所有组合(递归实现)
- 从数组中取出n个元素的所有组合(递归实现)
- 从数组中取出n个元素的所有组合(递归实现)
- 从数组中随机取出4个不重复的数字
- 从数组中取出n个元素的所有组合(递归实现)
- 从数组中取出n个元素的所有组合(递归实现)
- iDUP 成员门户(Portal)功能简介V1.0
- a += a -= a*a
- JavaServlet之http协议详解
- 自己关于Qt坐标的错误使用
- HDU 2084 基础DP
- 百度笔试题-从20数组内取出最大的500个
- 如何联机调试和发布程序(99$)
- 关于Java方法参数的个人补充
- 求二进制中1的个数
- Linux-epoll
- rnqoj-73-展演队型-dp
- 网络子系统42_ip协议数据帧的接收
- 动态更换view类的背景---StateListDrawable的应用
- lightoj 1422 区间DP