在我的朋友网络中找到最受欢迎的赞

Posted

技术标签:

【中文标题】在我的朋友网络中找到最受欢迎的赞【英文标题】:Finding the most popular likes in my friend network 【发布时间】:2012-09-09 12:10:34 【问题描述】:

我正在努力寻找在我的朋友网络中最受欢迎的点赞。 “在我的朋友网络中最受欢迎”被定义为“我的朋友喜欢的次数最多”。

假设每个朋友都有一个唯一的 id 并且有许多喜欢的页面。所以,给定一组这样的朋友,我想找出点赞最多的朋友,以及喜欢这个东西的朋友。本质上,我想展示“你的朋友 X、Y 和 Z 喜欢这个”之类的内容。

我的第一个解决方案是使用 Map(用于存储反向映射:like->set)和 Priority Queue(用于查找前 N 个)。这是我的算法(使用 C++ STL):

map< like, set<friend> > like2friendsMap;
for each friend 
  for each like 
    like2friendsMap[like].insert(friend); //populate the map
  


priority_queue< pair<like, int> > pq;
for each like in like2friendsMap 
  int count = like2friendsMap[like].size(); //no. of friends who like this or "popularity"
  pq.push(like, count); //count is the priority


map< like, set<friend> > result
for i in 1 to N  //N is how many popular items I want
   result = pq.top();  //gives me the element with highest priority (most popular like)
   pq.pop();

由于 STL 在内部使用红黑树来实现映射,并为优先级队列使用最小/最大堆,这种方法对我来说似乎很快。但是如果我有 100 个朋友,每个人都有 100 个喜欢,那么内存使用量会很大。当然,我应该使用朋友 id 和点赞 id 进行所有计算,而不是存储整个对象,这会大大减少内存使用量。

还有哪些算法或数据结构可以用来提高效率(提高速度,减少内存)?出于某种原因,我无法针对每个喜欢存储朋友列表,它必须在运行时计算。我正在使用 C++ 进行开发,因此使用 STL 或 boost 的解决方案会更好。

【问题讨论】:

即使是一千个有一千个赞的朋友也只是一百万个赞。今天,计算机可以处理数十亿个对象。 也就是说,这通常是我在 SQL 中执行的操作。数据库可以处理数十亿行,而这种分组是 SQL 的生计。 @MSalters 问题是它可以在大约 100 个线程中并行运行,因此减少内存占用是一个显着的好处。 【参考方案1】:
create an integer list allPages which can be referenced by page
initialize it with 0
for every friend f

    for every page p liked by f
    
        allPages[p]++;
    

get the maximum of the allPages[p]

如果P是页数,则空间复杂度为O(P)

如果F 是朋友的数量,L 是每个人喜欢的平均页面数。那么它的时间复杂度将是O(F*L)。因此,即使您再次遍历所有朋友以查看谁都喜欢该页面,也不会增加太多复杂性。

O(F*L) + O(F) would remain O(F*L)

我认为最好再次迭代而不是存储朋友。

或者您可以存储页面的反向引用本身。也就是说,对于每个页面,存储喜欢的朋友列表。这不会占用太多空间,并且会以最低的复杂性完成您的工作。

【讨论】:

虽然这解决了查找最受欢迎页面的问题,但我必须再次扫描所有朋友才能找到喜欢他们的朋友。【参考方案2】:

我不明白你为什么使用priority_queue。当然,它在容器更改时有效地跟踪最大元素。但是你只需要单次操作,在第一步之后。总结:

priority_queue< pair<like, int> > pq;
std::priority_queue< pair<like, int> >::const_iterator max_friends = pq.begin()
for(i = like2friendsMap.begin() to .end())  
  if (max_friends->size() < i->size()) max_friends = i;

当然,这仅适用于 N=1,但对于“你的朋友 X、Y 和 Z 喜欢这样”的首选,这就足够了。

【讨论】:

我其实是想找到前 N 个最受欢迎的点赞,这就是我选择优先队列的原因。【参考方案3】:

既然您对寻找“最受欢迎的赞”感兴趣,这是否意味着您只对“前几名”感兴趣,例如前 5 名、前 10 名等?如果是这样,一种可能的方法是重新排序事物,以便您迭代每个喜欢,计算 N,与该喜欢相关联的朋友的数量,然后仅在该喜欢进入运行时对其进行进一步处理顶部 X' 列表。棘手的部分是使用这样的循环结构有效地计算 N(天真的实现将遍历每个朋友。喜欢每个朋友,每个喜欢..yuck..),但好处是如果 N 足够小,你可以放弃所有与此相关的数据都来自内存,并且不会对其进行任何进一步的处理。也就是说,如果您有一个“前 10 名列表”,并且您已经向该列表添加了 10 个喜欢,并且当前喜欢的 N 小于“前 10 名列表”中最小的 N,那么您知道喜欢是无关紧要的.基本上,你做一个交易,你做一些冗余循环以换取显着减少的内存占用。这些循环也可以合理地并行化,所以额外的循环可能不是那么糟糕。很难说如果不尝试它是否对您的特定用例更有效,但如果“前 10 名”风格的输出满足您的要求,则可能值得朝这个方向探索。

【讨论】:

以上是关于在我的朋友网络中找到最受欢迎的赞的主要内容,如果未能解决你的问题,请参考以下文章

如何找到最受欢迎和最不受欢迎的产品?

在 mysql 上选择我的数据库最受欢迎的目的地

如何在 HiveQL 中计算每个城市中最受欢迎的设备、操作系统、浏览器?

黑客中最受欢迎的工具排行榜

Sublime Text 3最受欢迎的配色主题-超炫

最受欢迎的校园零食