【问题标题】:Complexity of *in* operator in PythonPython中*in*运算符的复杂性
【发布时间】:2012-12-02 18:41:51
【问题描述】:

Python 中in 运算符的复杂度是多少?是θ(n)吗?

和下面的一样吗?

def find(L, x):
   for e in L:
       if e == x:
           return True
   return False

L 是一个列表。

【问题讨论】:

  • 这取决于容器的类型,因为将它与字典或集合一起使用会比使用数组快得多。
  • @BasicWolf 我用过L,所以是list
  • @Rastegar L 并不意味着列表。 seq 是想要暗示列表的最常见选择。 L 是一个糟糕的变量名。单字母不好,大写表示它是一个类。即使它是特别的东西,Python 也是动态的,所以在这样的情况下明确说明它。
  • L 表示list?我的 libtelepathy.so 可能已经过时了。
  • @GarethLatty 使用 lst 也是定义list的好名字

标签: python time-complexity


【解决方案1】:

in 的复杂性完全取决于L 是什么。 e in L 将变为 L.__contains__(e)

请参阅time complexity document,了解几种内置类型的复杂性。

这是in的摘要:

  • 列表 - 平均:O(n)
  • set/dict - 平均:O(1),最差:O(n)

set 和 dicts 的 O(n) 最坏情况非常罕见,但如果 __hash__ 实施不当,可能会发生这种情况。仅当您的集合中的所有内容都具有相同的哈希值时才会发生这种情况。

【讨论】:

  • 有人碰巧知道 OrderedDict 的“in”运算符的复杂性吗?
  • 经过一些测试,我可以确认Python 2.7中OrderedDict的复杂度在一般情况下似乎是O(1)。
  • @Josh Sherick 您不必提供测试,您所需要的只是OrderedDict 的来源,并且您会发现:OrderedDict 继承自dict,所以大多数操作(当然,除了例外)具有相同的复杂性
  • 元组的“in”运算符的时间复杂度是否也是O(n)?
  • @whitehat 线性。
【解决方案2】:

这完全取决于容器的类型。散列容器(dictset)使用散列,本质上是 O(1)。典型序列(listtuple)按照您的猜测实现,并且是 O(n)。树将是平均 O(log n)。等等。这些类型中的每一种都将具有适当的 __contains__ 方法,并具有其大 O 特性。

【讨论】:

  • 的价值是包括生成哈希的开销。
  • 散列数据类型包括 dictset(以及可能的其他类型)
  • @Woot4Moo:当您谈论渐近复杂性时,这无关紧要。生成哈希的开销是恒定的。当您处理 N 的小值时,分析变得很重要,因为对于小 N,例如 100 >> 2N。但这与 OP 所问的问题不同;对于巨大的 N,100
  • @abarnert 好吧,它实际上非常相关,因为您不会随意选择数据结构。您必须考虑结构的用途和最常见的使用方式,因此考虑哈希函数的时间量实际上很重要,尤其是在每次程序迭代都必须计算 has 的情况下。
  • @Woot4Moo:如果有人问渐近复杂度,要么(a)他们希望处理一个大的 N,要么(b)他们是个白痴。我假设 OP 是案例 (a),但无论哪种方式,常数因子都与答案无关。
【解决方案3】:

这取决于您正在测试的容器。这通常是您所期望的——有序数据结构是线性的,无序数据结构是常数。当然,这两种类型(有序或无序)都可能由树的某些变体支持。

【讨论】:

  • @ZoranPavlovic A in B 测试A 是否在B 中。
  • 我绝对希望有序结构中的对数时间。
  • @dedObed 为什么会这样?您是否希望 python 已经知道您的数据是否已排序?
  • 因为如果有一个容器设计为订购,显而易见的原因是允许对数查找。但我想这只是一个命名问题,我会在你写“有序”的地方使用“线性”,一切都会好起来的。 (在我的脑海里——英语是这里的第二语言。)
猜你喜欢
  • 1970-01-01
  • 2013-08-10
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多