对于M个有序集合的前N个项目,最有效的方法是什么?

时间:2014-06-10 10:27:39

标签: algorithm sortedset set-union

假设您有4个排序集,其中包含成千上万的键和分数。由于它们是有序集合,因此可以在对数时间复杂度下完成顶级项目。

简单的方法是获取集合的联合,然后获得最顶层的项目。但这样做至少与所有集合中所有项目的总和呈线性关系。

我能想到的最好方法是:

  1. 从每一组中取出前N项
  2. 找到排名最低且该排名最高分的项目。
  3. 根据套数得分。 (分数低于此值的任何键都不能位于前N个)
  4. 取得这些钥匙的结合。 (忽略分数)
  5. 查找所有组中所有键的分数。 (一个密钥可能在一组中得1,在另一组中得10000)
  6. 就像找到可能位于顶部列表中的所有键,然后使用这些键进行联合。可能有更有效的方法来限制要考虑的项目数量。

    [编辑] 键出现在一个或多个集合中,它们的总和分数决定了最终得分。 因此,所有具有较低分数的集合中的密钥可能比仅具有高分的密钥具有更高的分数。

1 个答案:

答案 0 :(得分:3)

你提出的算法似乎很尴尬。只需采取以下措施之一:

简单方法

for i = 1 to n
    loop through all sets and look at their smallest element,
    pick the smallest element and remove it from the sets

复杂性:     O(n * s)其中n是您想要的项目数,s是集合数。

当然,如果不允许从集合中删除元素,您还可以在每个集合中保留iterators,以便按排序顺序从中获取元素,而无需更改集合。

更有效的方式

在每个集合的所有最小元素上维护优先级队列。每当从该优先级队列中删除最小元素e时,重新插入e所来自的集合中的下一个元素。

复杂性:假设一个简单的优先级队列O(log n)'插入'并O(log n)'删除最小元素'复杂。有更好的像斐波那契堆,但这个会做得很好。然后我们有:

  • s插入以在开始时填充优先级队列,因此O(s log s)
  • n"删除最小元素" +插入一个新的O(n log s)(因为队列中总是有s个元素)

因此,我们实现O(s log s + n log s)更好。

比较

只要s非常小,算法之间就不一定存在很大差异,您也可以选择简单的算法。如果你有很多套装,那么你一定要采用第二种方法。

查找复杂性

在我的分析中,我省略了对数查找因子以找到每个集合的最小元素,并假设每个集合中的最小元素可以在O(1)中检索,就像在排序列表中一样。将查询成本从O(1)改为O(log n)只会引入一个不会改变算法的额外因素。此外,您通常只在第一次查找时支付O(log n)次。之后,您通常会有一个最小元素的迭代器。然后使用迭代器访问每个其他元素只有O(1)