【算法】新浪微博笔试题:找出共有2个以上标签的用户对

这里看到新浪微博的一道面试题:给定sina微博的全部用户(1亿以上)和标签(uniq的标签30万左右)的关系, 系统找出共有2个或以上标签的用户对,并给出这些标签是哪些。

看起来是一个实践中的题目,很靠谱,值得花点时间研究一下。

(算法远远谈不上精通,只能拍脑袋想想了。。。)

解题思路:

从搜索的角度,来讲解题思路很简单,

(1)建立倒排索引,输入是user id, tag list, 输出是tag id,user list。

(2)求不同tag的user id集合交集,应该分成若干子步

       2.1 对tag两两求交集,得出的是共有两个标签的用户对。

       2.2 对共有两个标签的用户集合,再和第三个标签做交集,得到共有三个标签的用户对。

       ...... 依次类推,每次都使用最小的结果,直到没有结果。

优化空间:

a) 每次循环都使用最小的集合,即尽可能后面的中间结果。

从算法上说,中间也可以采用对两个共有有两个标签用户做交集,得出共有四个标签的用户对;对有两个标签和有三个标签的用户做交集,得出共有五个标签的用户对;等等这些手段,每次都使用最少的循环次数。

从工程实现上说,串行的实现未必是最优的,如果mapreduce有足够的task可以进行的话,并行度越高越好。

b) tag list使用tag id,而不是使用字符串。

对于30万(300k, ~2^19)的词建立词典还是有帮助的。

c) 用户集使用trie(前缀表),而不是使用数组

一亿(100M, ~2^27)使用ID的话,大概要占一个Int,倒排一下就相当于复制多份,实在是浪费空间。用数组的话,做交集和不是很方便,还是需要排序。用前缀表的话,天生就是可以排序的,又可以节省部分空间,merge的话直接树干merge还可以直接砍掉不重合的树枝,想想应该是合算的。

工程实现:

a)延迟加载

100M的用户ID本身就400M,加tag信息估计超过1G,加上中间结果,内存一般都是放不下的,所以必须考虑换入换出。

b)持续更新

姑且不论是否需要,这个数据量和算法应该可以实现实时更新,比如一个用户添加了一个新tag,就在这个tag的user set中寻找同tag的用户。

中间结果也可以保留,比如tag1-tag2可以算作一个新的tag。。。

 

其他的继续思考。

 

 

posted @ 2013-01-12 20:51  utopiazh  阅读(1875)  评论(1编辑  收藏  举报