面试集锦之---Top-K问题(百度面试题)

百度面试题:
    搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。
    假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。

解题思路:

step1:查询统计

第一种就是进行排序了,可排序的方法有很多种,最简单的就是直接排序。可是如果单纯使用内排序将行不通,因为255B*1千万=2.3...G,所以如果一次性的将所有数据读入直接进行排序时行不通的。所以我们要借助内排序和外排序的结合对其进行排序。

知识补充:何为内排序和外排序。

我们一般提到排序都是指内排序,比如快速排序,堆排序,归并排序等,所谓内排序就是可以在内存中完成的排序。RAM的访问速度大约是磁盘的25万倍,我们当然希望如果可以的话都是内排来完成。但对于大数据集来说,内存是远远不够的,这时候就涉及到外排序的知识了。

  外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装人内存的部分,分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行归并排序。

  一般来说外排序分为两个步骤:预处理和合并排序。即首先根据内存的大小,将有n个记录的磁盘文件分批读入内存,采用有效的内存排序方法进行排序,将其预处理为若干个有序的子文件,这些有序子文件就是初始顺串,然后采用合并的方法将这些初始顺串逐趟合并成一个有序文件。

  预处理阶段最重要的事情就是选择初始顺串(就是如何对分割出来的各个小文件进行排序啦)。通常使用的方法为置换选择排序,它是堆排序的一种变形步骤如下:

  1.初始化堆

  (1)从磁盘读入M个记录放到数组组RAM中

  (2)设置堆末尾标准LAST=M-1

  (3)建立最小值堆

  2.重复以下步骤直到堆为空

  (1)把具有最小关键码值的记录Min也就是根节点送到输出缓冲区

  (2)设R是输入缓冲区中的下一条记录,如果R的关键码大于刚刚输出的关键码值Min,则把R放到根节点,否则使用数组中LAST位置的记录代替根节点,并将刚才的R放入到LAST所在位置,LAST=LAST-1;

  (3)重新排列堆,筛出根节点

以上排序方法的时间复杂度是O(nlgn)。但是我们可以有更好的方法。那就是利用hash表。我们设定用户输入的索引串为key,而索引串出现的次数为value。每次读入一个索引串,如果在哈希表中不存在该索引串则插入,并修改value,如果索引串已经存在于哈希表中,则增加value的值。而这个操作只需O(n)时间内就可以完成。

step2: 统计top-K

比如说我们要排名在前10 的索引串,那么我们可以对300万个数据进行排序,然后取出前十名。但是这样做的时间复杂度非常高:O(nlgn)。其中n为300万。因为我们只需要前十名的索引串,所以可以建立一个节点为11的最大堆。首先读入10个数据,并调整堆,使之成为最小堆,然后依次读入剩下的数据。每读入一个数据调整最小堆(时间复杂度是lg11),然后去掉根节点。当遍历完所有的索引串后,最小堆中去掉根节点后剩下的10个节点就是我们所要求的top10索引。总的时间复杂度是O(nlg10)。以上是利用了堆排序的思路进行top-k的统计。

所以解决top-K的总体思路是:首先建立哈希表,将索引串映射到哈希表中,此时统计出了索引串的出现次数,然后利用堆排序的思想求前k个索引串。


 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值