Python中* in *运算符的复杂性


78

inPython中运算符的复杂性是什么?是theta(n)吗?

与以下相同吗?

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

L 是一个列表。


3
它取决于容器的类型,因为将其与字典或集合一起使用将比与数组一起使用快得多。
Greg Hewgill

1
@BasicWolf我用L,所以它是名单
萨贾德Rastegar

5
@RastegarL并不表示列表。seq是要隐含列表的最常见选择。L是一个糟糕的变量名。单字母字母不好,大写字母表示这是一类。即使是特别的东西,Python还是动态的,所以在这种情况下要明确声明它。
Gareth Latty

1
Llist什么意思?我的libtelepathy.so可能已过时。
Zaur Nasibov

1
@GarethLatty使用lst也是定义list
r0ei

Answers:


136

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

有关几种内置类型的复杂性,请参见此时间复杂性文档

这是以下内容的摘要in

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

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


1
有人碰巧知道OrderedDict的“ in”运算符的复杂性吗?
Josh Sherick

1
经过一些测试,我可以确认Python 2.7中OrderedDict的复杂度在一般情况下似乎为O(1)。
Josh Sherick

@Josh Sherick您不必提供测试,您只需要提供测试的源,OrderedDict就可以发现:OrderedDict继承自dict,因此大多数操作(当然,有例外)具有相同的复杂性
maxkoryukov

元组的“输入”运算符O(n)的时间复杂度也是吗?
继承怪胎

与生成器一起使用时,“ in”运算符的时间复杂度是多少?
白帽

12

这完全取决于容器的类型。散列容器(dictset)使用散列并且基本上O(1)。您猜中会实现典型的序列(listtuple),它们是O(n)。树木的平均值为O(log n)。等等。这些类型中的每一个都将具有__contains__其big-O特性的适当方法。


价值的计算包括生成哈希的开销。
Woot4Moo 2012年

散列数据类型包括dictset(以及潜在的其他数据)
Dave

1
@ Woot4Moo:当您谈论渐近复杂性时,这无关紧要。生成哈希的开销是恒定的。当您处理较小的N值时,分析就很重要,因为对于较小的N例如100 >> 2N。但这是与OP询问的另一个问题;对于巨大的N,100 << 2N,这就是复杂性的全部。
abarnert 2012年

@abarnert好吧,它实际上是非常相关的,因为您不必随意选择数据结构。您必须考虑使用该结构的用途以及最常用的方法,因此,考虑散列函数的时间量实际上很重要,尤其是在必须每次程序迭代计算has的情况下。
Woot4Moo

@ Woot4Moo:如果有人问渐近复杂性,要​​么(a)他们期望处理一个大的N,要么(b)他们是个白痴。我假设OP是(a)情况,但是无论哪种方式,常数都与答案无关。
abarnert 2012年

-1

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


@ZoranPavlovicA in B测试是否A在中B
Marcin 2014年

1
我绝对希望对数时间处于有序结构中。
dedObed

@dedObed为什么会这样?您是否希望python已经知道您的数据是否已排序?
Marcin

因为如果有一个设计为要订购的容器,那么显而易见的原因是允许对数查找。但是我想这只是一个命名问题,我会在您写“ ordered”的地方使用“ linear”,一切都会好的。(在我的脑海中-以英语为第二语言。)
edObed
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.