如何在很大数量级的数据中(比如1个亿)筛选出前10万个最大值?
本人大三非计算机专业,自学web开发,前几天找实习面试php的时候面试官问我的算法题,没答上来本来准备最后问一下的,结果最后太紧张忘了问这题,回去之后没想到解法,希望知乎里大牛提供一个思路,什么语言都行<(。_。)>
=====================================================================
补充:初始是无序的,内存和磁盘并没说,我自己没有想明白这题的切入点也就没问在内存还是在磁盘,望能得到这两种情况都有的全面解答,多谢
回复内容:
问题是在 N 个数中,找到前 k 个数。1亿 = 100M 相对于现在的硬件来说是个很小的数,基本上可以都 fit 进内存。内存中找前 k 个数可以用 Quickselect 算法,一个类似 quicksort 的算法,平均复杂度是 O(N)。
如果总数据量更多,或者可用内存更小,可以把所有的数分成内存可以放下的多个部分,每个部分分别找前 k 个,最后把所有的数放在一起再找一次前 k,如果还放不下继续分堆。这个策略还可以让算法可以并行执行,有计算资源的时候降低整体执行时间。
这个算法比建一个大小为 k 的最大堆要快,因为后者最后得到的 k 个数是部分有序的,复杂度会变成 O(N log k),而前者得到的前 k 个数是完全无序的。 题主学过数据结构否?有个叫最小堆的东西。
------------------------------------------------------------------------
内存有限,可以把1亿个数据放在磁盘上,此外,在内存开辟一个可以容纳10万个数据的最小堆。
每次从磁盘上读取一个数据,若最小堆未满,则直接放入最小堆中,调整堆使其符合最小堆的性质;若最小堆已满,则将这个数与最小堆根结点上的数值进行比较,若比根结点的数值大,则替换掉根结点上的值,然后重新调整最小堆使其符合最小堆的性质。
遍历完1亿个数据后,这个容量为10万的最小堆里面存放的就是前10万个最大值了。 好好回答一下吧。
首先对于1亿的数据量,要求不高的话,大可只使用一个最小堆来维护前10万个最大的数。
不妨设数的总数为N,需要选出的数为M,那么这种方法带来的时间复杂度为:

这个方法最大的缺点是没有并行计算。
如果比1亿数据量再大,比如到100亿这个量级,那么就需要使用并行计算了,下面我详细说一下我的思路。
1) 首先将这些数据随机分成K堆,不妨假设正好平均分配,时间复杂度为

2) 使用K个任务并行的选出每一堆的前M大的数,这一步的时间复杂度为

3) 使用多路归并排序选出这K组序列的前M大的数,这一步的时间复杂度为

因此假设第2步并行完成,那么总体的时间复杂度就是

但是还没完,注意到2)中每个序列都选了前M大的数,这个是可以继续改进的。
我们可以想象一种场景:2个桶里总共有10个球,球是随机分布的,规定一种操作可以从这2个桶里拿至多L个球,这时我们怎么确定这个L使得我们能够以一个我们能接受的概率拿到所有的球?
显然当L=10的时候,我们当然可以100%的拿到这全部球,但是开销太大了。由于球是随机分布的,可以知道10个球全部落入落入一个盒子里的概率非常的小,是

既然我们牺牲了一部分可靠性降低了开销,那么为什么不能把L设的在低一点?究竟应该设多低?
这其实是另外的一个问题了,我认为为了解决这个问题不应该从L入手,而是我们设定一个最低能接受的可靠性概率P,找到最小的L满足我们要求的P即可。
因此我们可以使用如上方法优化2)。设我们要求的最低可靠性为P, 优化函数为

2) 使用K个任务并行的选出每一堆的前



我可以给出一个数

但是必须解决的问题是可靠性问题,但这个问题其实很好办,只需要验证一下在3)时有没有把一个序列用尽,如果用尽了并且最后一个数不是这个序列里的最后一个数,那么说明这个序列的第

所以这时我们得到了一个以P为成功率的算法,这个算法可能比未优化前快好多倍,但是有(1-P)的中奖概率。欣慰的是我们可以判断中没中奖,再不济就是抛弃这次的结果再跑一次未优化前的算法呗。 堆排序,+ 分而治之 m取前n
以取小为例吧。我喜欢小。
以数据总量,分:小、中、大,三种情况来分析。
1、小:全部读入内存,排序,取前n。
2、中:
2.1:分几次读入(次数为k=总数据/内存大小),分别排序、写回读入点。致全部读一遍。形成k个顺串(称之数据锥)。
2.2:各锥读取一节(量为内存/K),到内存(称之:锥节)。
2.2:各锥节尖做比较,小的写到另一块内存区(称之输出缓区)。如,某锥缓节空,读该锥的下一节。
2.3:致输出缓存区满。
2.4:写到结果文件。
2.5:结果够,结束。否则,继续2.2。
3、大:
3.1:若干单机,做2.1到2.3,暂停。
3.2:另一单机,做总机。从各单机输出缓存区,读一节到总机内存区(称总锥节)。
3.3:各总锥节尖做比较,小的写到总机的另一块内存区(称之总输出缓存区)。如,某总锥节空,读该锥对应单机输出缓存的下一节。
3.4:总缓存区满,写到结果文件。
3.5:结果够,结束。否则,继续3.3。
对于数据量大的情形。做顺串是免不了的。
以上算法,结果够时,会提前结束。
而锥节,总归比较小。因此,可能用不着 @皆传 的中奖法。
虽然中奖法很好玩。 最小K个数,思路和这个很类似。 很久没有碰数据结构了,只能说下思维框架。
1.先遍历前10万个数字,放到一个有序数据结构中,并且记录下这组数的最小值B;
2.遍历后面1亿-10万个数字,取出一个数字A,和有序结构中的最小值B进行比较,如果大于最小值B,则A进入有序数组,最小值B退出有序数组;
3.重新计算有序数组的最小值B;
4.重复这个过程直到结束。
---------------------
遍历1亿个数字是无法缩短时间的,那么程序的性能就在于如何在10万个数字尽快找到最小值了。
这个是二叉树最擅长的问题,你在遍历的同时也已经完成了二叉树的排序和插入工作。
不好意思的是,我已经基本忘记二叉树怎么写了。o_o||
先遍历,然后分堆,比如0-999999为一堆,100000-199999为二堆,
即n堆的范围是(n-1)*100000到n*100000-1
分好后,从最大的堆往前取,直到凑够,
比如,如果第一个堆的数量在10W个以上,那么可以继续分堆,可以继续分堆,缩小范围,也可以用排除法,比如最大的堆的数量在110000.则取这堆最小的10000,排除即可。
如果10W个数分布在几个堆里,那么必然存在前几个堆全取,最后一个堆取部分,最后的临界堆,这时可以继续分堆,也可以用双向循环链表取少量的top N.
当然也可以用一个10W节点的双向循环链表,插入去尾。
时间复杂度是 n log n * m
其中,n=100000,m是数组长度,
年前百度复合搜索部面试php,有个胖子面试官问过取top N问题,回答的是用双向循环链表,节点数就N。不过当时情况是,n很小,只有5.
构建二叉树要好一些,不过,当场写不出二叉树了,所以就没采取二叉树。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

PHP和Python各有优势,选择应基于项目需求。1.PHP适合web开发,语法简单,执行效率高。2.Python适用于数据科学和机器学习,语法简洁,库丰富。

PHP是一种广泛应用于服务器端的脚本语言,特别适合web开发。1.PHP可以嵌入HTML,处理HTTP请求和响应,支持多种数据库。2.PHP用于生成动态网页内容,处理表单数据,访问数据库等,具有强大的社区支持和开源资源。3.PHP是解释型语言,执行过程包括词法分析、语法分析、编译和执行。4.PHP可以与MySQL结合用于用户注册系统等高级应用。5.调试PHP时,可使用error_reporting()和var_dump()等函数。6.优化PHP代码可通过缓存机制、优化数据库查询和使用内置函数。7

PHP和Python各有优势,选择依据项目需求。1.PHP适合web开发,尤其快速开发和维护网站。2.Python适用于数据科学、机器学习和人工智能,语法简洁,适合初学者。

PHP在电子商务、内容管理系统和API开发中广泛应用。1)电子商务:用于购物车功能和支付处理。2)内容管理系统:用于动态内容生成和用户管理。3)API开发:用于RESTfulAPI开发和API安全性。通过性能优化和最佳实践,PHP应用的效率和可维护性得以提升。

PHP仍然具有活力,其在现代编程领域中依然占据重要地位。1)PHP的简单易学和强大社区支持使其在Web开发中广泛应用;2)其灵活性和稳定性使其在处理Web表单、数据库操作和文件处理等方面表现出色;3)PHP不断进化和优化,适用于初学者和经验丰富的开发者。

PHP主要是过程式编程,但也支持面向对象编程(OOP);Python支持多种范式,包括OOP、函数式和过程式编程。PHP适合web开发,Python适用于多种应用,如数据分析和机器学习。

PHP适合web开发,特别是在快速开发和处理动态内容方面表现出色,但不擅长数据科学和企业级应用。与Python相比,PHP在web开发中更具优势,但在数据科学领域不如Python;与Java相比,PHP在企业级应用中表现较差,但在web开发中更灵活;与JavaScript相比,PHP在后端开发中更简洁,但在前端开发中不如JavaScript。

PHP和Python各有优劣,选择取决于项目需求和个人偏好。1.PHP适合快速开发和维护大型Web应用。2.Python在数据科学和机器学习领域占据主导地位。
