假设您有4个排序集,其中包含成千上万的键和分数。由于它们是有序集合,因此可以在对数时间复杂度下完成顶级项目。
简单的方法是获取集合的联合,然后获得最顶层的项目。但这样做至少与所有集合中所有项目的总和呈线性关系。
我能想到的最好方法是:
就像找到可能位于顶部列表中的所有键,然后使用这些键进行联合。可能有更有效的方法来限制要考虑的项目数量。
[编辑] 键出现在一个或多个集合中,它们的总和分数决定了最终得分。 因此,所有具有较低分数的集合中的密钥可能比仅具有高分的密钥具有更高的分数。
答案 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)
。