我有一个(大)整数集S
,我想运行以下伪代码:
set result = {};
while(S isn't empty)
{
int i = S.getArbitraryElement();
result.insert(i);
set T = elementsToDelete(i);
S = S \ T; // set difference
}
函数elementsToDelete
是有效的(在S
的初始大小中是次线性的)并且T
的大小很小(假设它是常数)。 T
可能不再包含S
中的整数。
有没有办法实现比O(| S | ^ 2)快的上述?我怀疑我应该能得到O(| S | k),其中k是elementsToDelete
的时间复杂度。我当然可以使用std::set_difference
以简单的方式实现上述内容,但我的理解是set_difference
是O(| S |)。
答案 0 :(得分:1)
使用std::set S;
,您可以:
for (auto k : elementsToDelete(i)) {
S.erase(k);
}
当然erase
的查询是O(log(S.size()))
,而不是您要求的O(1)
。这可以通过std::unordered_set
来实现,假设没有太多的碰撞(一般来说这是一个很大的假设,但通常尤其如此)。
尽管有名称,但std::set_difference
算法与std::set
没有多大关系。它适用于您可以按顺序迭代的任何内容。无论如何,它不适用于容器的就地修改。由于T.size()
在这种情况下很小,因此每次删除一批元素时,您确实不想创建新容器。在结果集足够小的另一个例子中,它比重复erase
更有效。
答案 1 :(得分:0)
C ++库中的set_difference具有O(|S|)
的时间复杂度,因此它不适合您的目的所以我建议您使用S.erase()删除O(logN)
中实现的S中的set元素作为BST。因此,您的时间复杂度降低到O(NlogN)