从另一组整数中有效地删除一组整数

Efficient removal of a set of integers from another set

本文关键字:一组 整数 删除 有效地      更新时间:2023-10-16

我有一组(大)整数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|)。

使用 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更有效。

C++库中的set_difference具有O(|S|)的时间复杂度,因此它不适合您的目的,因此我建议您使用 S.erase() 删除 S 中的 set 元素O(logN)实现为 BST。因此,您的时间复杂度降低到O(NlogN)