锁定老帖子 主题:迅雷的一个面试题
精华帖 (8) :: 良好帖 (3) :: 新手帖 (0) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2012-03-01
我看到的是已经排序好了,为什么不直接查找这个用户的信息看看他排序标识是多少呢?
|
|
返回顶楼 | |
发表时间:2012-03-01
最后修改:2012-03-01
kidding87 写道 终于有人说了我说的东西。。。
你们难道就没发现别人说的是数据源,不是数据库 那么多数据select * from table where id=?没有索引这个的效率都低死,数据库还不是一个个找 的确,题目强调了是【数据源】,并且是有序的数据源,没有说具体的存储形式,用数据库,用文件系统,还是用缓存服务器集群......;其实大多数人一看到2亿条数据都想到自己采用怎样形式去存这个数据了,而忽略题目的本意是怎样快速有效的找出用户的排名;依我个人的愚见,用户登录系统时找到用户的分数排名,要到数据库去找,或是到文件系统去找花费不菲而且效率也不见得好,一般会放到缓存服务器集群中。当然其实数据源的存储形式我们不用去操心。用户登录肯定已经获取到id和自己的分数,我们就假设已经知道用户id和用户分数(这是比较合理的假设)。 数据源既然【有序】那么我们肯定就有办法(是什么办法根据数据源具体的存储形式可以写个方法<当然有可能数据源本身可以提供>)取到指定位置的元素。 1.获取数据源的最后一个元素和数据源的第一个元素的 score, 将这2个score 相减 得到的 最大分数与最小分数的差值 S1。 2.用得到的分数差值 除以 数据源的元素数量 得到 平均每个用户之间的 分数差 V1; 3.将用户的分数US 减去 数据源中最小分数 得到用户与最小 分数之间的差值 S2, 4.W = S2 / V1 ,W 为我们估算的用户在所有用户中的排名数量 5.取出W处的元素的score WS 6.如果 用户的分数US 小于 WS,则从 W处开始向前查找用户的排名,如果US大于 WS 则从W处开始向后查找用户的排名,用户的排名就在附近,不用加载太多数据。如果US的只等于WS,那么恭喜你了。 7.这个算法没有考虑分数相同并列排名的处理,我想迅雷也许也没有处理并列排名的情况,只是获取数据源中的具体位置。 8.如果分数分布特别不均匀的话,可以递归使用上面的方法多算几次,直到US 和 WS 相差非常小(小到一个阀值)再从W处开始向前或向后查找定位。 |
|
返回顶楼 | |
发表时间:2012-03-01
二楼的方法很好啊,这玩艺用不到数据库吧
|
|
返回顶楼 | |
发表时间:2012-03-01
yzsunlight 写道 bao231 写道 我感觉这个没什么难的啊,有两个方法
1.用数据库的话,采用分表的策略,每个表里的数据肯定知道吧,查看在哪个表里,计算偏移量,数量除以总数,就是结果。 2.如果自己存储数据结构话,scores采用10层的跳表顺序存储,scores与scores采用差值算法压缩存储量,这样一个一个遍历,计算出是第几个,然后除以总数 能不能说的具体点 人家已经说的很清楚了,真不明白还要说的多具体。 |
|
返回顶楼 | |
发表时间:2012-03-01
最后修改:2012-03-01
我觉得这个问题完全可以这样解决,前提是oracle数据库:
select scores,rownum from table where id=xx 都说了已经排好序了,rownum完全就是当前用户的排名。 再补充一下,用户登录就有自己的分数,这说明了什么,说明他是要从这个表中查分数的,那么完全可以顺便查rownum。而count(1)这种形式,一旦数据量大,非常消耗时间,有人说select * from table_name在数据量大的时候就不消耗时间吗?没错,数据量大的确比小要多消耗一点,但是根据我个人经验,一旦做了索引,那么select * from table_name where id=xx这样的语句在2条和2百万条时,响应时间几乎没有差别。 |
|
返回顶楼 | |
发表时间:2012-03-01
最后修改:2012-03-01
我写了一篇文章来解答《海量用户积分排名算法探讨》
http://www.cnblogs.com/weidagang2046/archive/2012/03/01/massive-user-ranking.html |
|
返回顶楼 | |
发表时间:2012-03-01
这个肯定是二分查找,但是数据那麽大,没法一下子拉到内存,所以是存文件,存文件的化采用跳表得方式,进行二分查找。
|
|
返回顶楼 | |
发表时间:2012-03-01
create table rank(id bigint not null primary key, rank bigint not null);
|
|
返回顶楼 | |
发表时间:2012-03-01
在具体的应用中,每个用户的分数是不是在随时变化着呢?比如游戏得分。
其实准确的名次没什么意义,可以利用概率啊。 随机取万分之一的数据排序 得到的名次乘以2万 就可以了。 |
|
返回顶楼 | |
发表时间:2012-03-01
hardPass 写道 tsxm 写道 hardPass 写道 就一定要用数据表来完成么?
CPU,内存,外存 同学们啊! 桶排序呗, 直接在程序中搞个数组,数组的下标就是分数,元素是每个分数对应的人数。 具体的,如果不需要精确计算,为了减少同步及遍历计算的性能损失,可以为每个数组元素设定一个预留值。 都说内存不够了,用外存估计速度太慢 1G内存还不够?如果现在排名第一的是1亿分,也就是一个长度为1亿的数组而已 300MB左右就够了,剩下的内存还可以再维护个计数缓存的数组(每个元素是上面数组希格玛,0到i),数组长度是上面数组一样 你只允许255个人得同样的分数啊... |
|
返回顶楼 | |