从100万数据中找出最大10条的最优算法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从100万数据中找出最大10条的最优算法相关的知识,希望对你有一定的参考价值。

我面试的时候有问到过,因为数据量很大,所以要同时考虑空间问题。标准答案是采用堆排序。

具体做法是:
构建一个只有10个元素的min-heap,那么根结点就是这10个数中最小的数,然后开始遍历数组,如果遇到的数比min-heap的根结点还小,直接跳过,遇到比min-heap根结点大的数,就替代根结点,然后对这个min-heap进行维护(也就是排序,保证heap的特征)。那么遍历完数组后,这个min-heap的10个元素就是最大的10个数。

关于堆排序的代码应该不难找追问

谢谢你的答案,可是遍历数组,100万的数据量花费的时间不也同样很大吗?

追答

那你觉得和对100w个数排序比呢...遍历的时间复杂度只是n,而任何排序最快也需要nlogn的时间。
当然维护这个heap实际也是在排序,只不过这里的n很小只有10。
而且另一个重要原因是你采用整个数组都排序的话,100w数需要大量的额外空间。

说快速排序因为in place不占空间是不对的,可以去wiki一下快速排序看看他的空间复杂度是怎么算的。这个问题在美国是比较经典的程序员面试题,我和同学一共被问过3次,并不是在这里胡说。我第一次回答是快速排序,面试官不满意,后来结束了我问他应该是什么,他说你有没有听过堆排序。后来在一本程序员面试书上才看到这个答案。

参考技术A var collection = new int[] 1, 5, 9, 3, 4, 6, 2, 4, 8,44,99,33,22 ............ ;

var top = 10;

int[] result = new int[top];

foreach (var item in collection)

//判断当前值是否大于结果集中的最小值.
if (item > result[0])

//将当前值插入结果集
for (int i = 0; i < top + 1; i++)

if (i == top || item < result[i])

//顺移结果集中小于当前值的值.
for (int j = 0; j < i - 1; j++)

result[j] = result[j + 1];

result[i - 1] = item;
break;





return result; //返回结果.
参考技术B 这个东西叫顺序统计学,有个线性时间的递归算法叫randomize-select,有点像快速排序。

你查一下文献,很快就可以掌握了

用堆排序是o(nlgn),random-select线性时间就可以做到。。。。用排序是顺序统计学的上界,而且顺序统计学是in place的,不占空间,拜托不懂不要瞎说

快速排序是原地排序,空间复杂度主要是在递归栈上,平均深度是n(lgn),最坏情况递归深度o(n),你觉得空间复杂度大么。100w数据o(n)也不算大吧,你的排序算法时间复杂度是o(nlgn)。

问题是顺序统计学不是快速排序,有点类似,也是递归。如果你用chosen-pivot算法,floyd的pivot选择法,可以把最坏事件情况也控制在o(n)内,而且顺序统计学只是递归一半,空间复杂度是绝对的n(lgn)。

以上是关于从100万数据中找出最大10条的最优算法的主要内容,如果未能解决你的问题,请参考以下文章

漫画:五分钟学会贪心算法!

ML: 聚类算法R包 - 模型聚类

计算机网络-网络层-路由算法

实验1 最小生成树问题Kruskal+Prim

数组最大差值的最优解法(动态规划)

100w个数中找出最大的前K个数