TopN问题

TopN问题是Android面试中经常遇到的问题,集在一个很大的集合中找到前N大的树,如给出10亿个无序的整数集合,从中找到前100或者前1000等的数。

这种问题首先排序一定能解决,例如快速排序或者冒泡排序,这里如果实用排序算法来实现的话冒泡排序可能要优于快速排序(因此只需要找出前100或者前1000大的数即可,即使使用冒泡排序也只需要冒泡100次或者1000次即可,算法的时间复杂度是100N或者1000N,而使用冒泡排序的时间复杂度是Nlogn)。

无论是什么排序都可以实现TopN的问题,但是时间复杂度相对较高,因此可以考虑分治的思想与快速排序相结合,首先类似于快速排序算法,从中任选一个数作为标兵,然后对整个集合进行partition分区,将大于它的至于左边,小于它的至于右边如下图所示。

如果前一部分的集合的长度等于N排序结束,如果前一部分的集合的长度大于N,则从前一部分中在随机查找出一个数作为标兵,对该集合做partition分区操作;如果该集合的长度小于N,对小于标兵T2的集合做partition分区操作,判断右边大于T2的集合是否等于N-S(num>T1),以此类推

这样的话算法的时间复杂度是O(N)。

因为第一次做partition的时间复杂度一定是O(N),第二次来看数据已经减半了,以此类推,因此总的时间复杂度为O(N) = N + N / 2 + N / 2^2 +N / 2^3 +...,因此总的时间复杂度是O(N)。

实现分治算法的前提是需要有足够的内存空间,如果内存空间不够,例如只有2G的内存空间,而以Int32位来计算,10亿个数需要4G的内存空间开存储,现在不满足条件,这时就需要使用文件分别存储,

第二次再从其中一个文件中读取数据,这样的话也是可以实现的,但是缺点是需要多次磁盘的读取和写入操作,效率相对不高。

使用如果内存不足的情况下使用文件操作效率较低,因此可以考虑分布式计算,例如有1000台电脑,每一台电脑计算1百万个数中的前1000大的数,然后将这1000*1000大的数再进行排序也能实现需求,这样的好处是计算较快,缺点也很明显,需要1000台电脑。

如果只有一台电脑的时候,可以考虑使用堆排序,首先先内存中开辟出一个容量为一千的小顶堆,然后将数组中的前1000个数据放入小顶推中并排序,根据堆的性质,堆中的每一个元素都比它的左右子节点中的元素小。后面每次进入的数堆排序字对进行一次堆排序,如果插入的元素比堆顶的元素小则直接丢弃,否则将堆顶元素替换并进行堆排序,从新构成小顶堆,以此类推。当所有的数据都处理完后,剩下的堆中的元素就是所要的10亿元素中最大的前1000个数。最后以此输出堆中元素。

这种方式的优点是所有的元素都只读区一次。不存在数据多次读取的情况。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    蚁前阅读 10,585评论 0 52
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序好...
    依依玖玥阅读 5,017评论 0 2
  • 一.简述如何安装配置apache 的一个开源的hadoop 1.使用root账户登陆 2.修改ip 3.修改hos...
    栀子花_ef39阅读 10,384评论 0 52
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    printf200阅读 4,134评论 0 0
  • 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部...
    zwb_jianshu阅读 5,025评论 0 0