this Python time complexity table中的设置条目,以及下面的评论确认,S.difference_update(T)
需要时间O(len(T))而S - T
需要O(len(S))。给出的理由是第一个的算法是"对于T中的每个元素将其从S"中移除,而第二个的算法是"对于S中的每个元素将其添加到新的集合中,如果不是在T"。
算法"对于S中的每个元素,如果它在T"中,则从S中删除它。工作得相同,是O(len(S))?为什么不做哪个更短?
我想我没有看到什么。
答案 0 :(得分:3)
从技术上讲,操作中并不需要S大于T. T
很可能实际上比S大得多:
>>> S = {1, 2, 3}
>>> T = {3, 4, 5, 6, 7, 8, 9}
>>> S - T
{1, 2}
因此,为所有操作选择一个或另一个算法将是一个任意选择,因为你根本不知道哪个实际上更短(如果你不知道这些集合)。
但总的来说,这并不重要。 S和T都是输入,O(|T|)
和O(|S|)
仍然是O(n)
,即线性。所以这无论如何都不是问题。
我已与the source核对,以进一步确认究竟发生了什么。
S.difference(T)
,S - T
(set_difference
):这会计算两个设置对象之间的差异。它遍历S中的元素并检查每个元素是否包含在T中。如果不是,则将其添加到结果集中。
如果S
远大于T
,则实施实际上会复制S并执行S' -= T
。由于这会在S中留下许多项目,因此比从空集开始便宜并继续从S添加元素。
S.difference_update(T)
(set_difference_update
):首先,它接受多个参数。所以从技术上讲,它不能检查T的长度和交换只是因为周围有多个Ts。更重要的是,它支持不自行设置的Ts(任何可迭代的),因此它只能通过迭代这些迭代并从集合中删除这些项来工作。
所以为此,迭代S
实际上是不可能的(因为我们在Ts中没有常数成员检查)。
事实证明,这就是为什么会发生这种情况的原因。这些原因大多隐藏在实际的set方法中,而不是操作符实现(虽然内部使用了这些方法)。虽然您可以进一步微观优化一些特殊情况,但如上所述,虽然从技术上讲,您仍然会留下O(n)
,但这并没有给您带来太多改进。在通常的应用程序中(特别是在Python中),这样的操作不太可能成为你的瓶颈。