topK问题
topK算法就是给出一堆数,在里面找出最大、最常出现的等一系列问题。
topK算法(常考)
方法1:K大小的数组存topK
维护一个K大小的排序数组,每次都和最后一个元素比较,如果比最后一个元素大的话,那么就把这个元素插入到排序数组中。因为元素的每个移动的次数可能是K,时间复杂度O(N*K)
方法2:K大小的堆存topK
维护一个K大小的小顶堆,每次都和堆最上面的元素作比较,如果比最上面的元素大,说明这个元素是目前的topK里面的元素,将这个元素和堆顶元素交换,更新堆。如果比最大的元素小,那么就不管这个元素。时间复杂度O(N*log(K))
查找一个网站访问量最多的200个检索单词
http://blog.csdn.net/v_july_v/article/details/6279498
方案1
第一步:如果能够加载到内存,直接用hash表统计每个单词出现的次数O(N)
第二步:将统计到的单词和对应的次数作topK排序算法O(N*log(K));
方案2
第一步:用trie树统计出每个单词出现的次数,时间复杂度O(N*单词平均长度)
第二步:用堆实现top200算法,时间复杂度O(N*log200)
如果内存里面不能够装下所有的数据,那么先将数据通过hash的方式,散列到多个文件里面,然后统计每个文件里面的每个关键字出现的次数,然后topK
在海量数据中查找重复次数最多的一个就是top1问题
用java统计一个文本文件中出现的频率最高的20个单词top20问题(A)
排序问题
有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序
方案1:如果所有的元素种类数能够装入到内存,那么就变成了上面的这个题。
方案2:如果不能够将所有的元素装入内存
第一步:将所有的文件重新shuffle到个不同的文件中(shuffle的key就是这些单词),当然每个文件都是用相同的hash函数。
第二步:对每个文件中的值进行排序
第三步:对这些文件进行归并排序(期间,已经排好序的部分写到磁盘,空出内存)
找重复值问题
在2.5亿个整数中找出不重复的整数
情况1:内存能够装得下这个位图
用位图操作,每个元素用两个bit,如果不存在用00,存在一次01,存在多次用10。
情况2:内存不能够装得下这个位图
将这个2.5亿个数根据最后Nbit划分为2^N个文件,每个文件内部再利用情况1的方法。
给40亿个不重复的unsigned int无序的整数,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
情况1:申请位图,每个位对应一个数,或者hash表,BloomFilter
情况2:内存不能放下:
如果这个40亿个数的位图不能够在内存里面放得下那么就可以将这40亿个数hash成为不同的文件1,2,3……。需要判断是否存在的数为Num,先用相同的方法hash出Num对应文件,然后再在对应文件里面作hash或者位图等。
另一道是在N个数中求前M大个数.
1)使用快速排序的思想,每一次当把一个数字放在正确的位置上的时候跟M进行比较
2)堆排序:建立一个大小为M的小顶堆。如果比堆顶的元素大的话就插入到堆中。