Python 中 list.index(x) 的复杂性
Posted
技术标签:
【中文标题】Python 中 list.index(x) 的复杂性【英文标题】:Complexity of list.index(x) in Python 【发布时间】:2011-08-20 07:08:50 【问题描述】:我指的是这个:http://docs.python.org/tutorial/datastructures.html
就大 O 表示法而言,list.index(x)
函数的运行时间是多少?
【问题讨论】:
可以找到索引操作的源代码here。是O(n)
。
它比我预期的要快得多。 %%timeit
说 2.2ns 而通过 ORM(暖查询集)获取属性是 80ns。
【参考方案1】:
使用以下代码检查时间。它的复杂度是 O(n)。
import time
class TimeChecker:
def __init__(self, name):
self.name = name
def __enter__(self):
self.start = self.get_time_in_sec()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
now = self.get_time_in_sec()
time_taken = now - self.start # in seconds
print("Time Taken by " + self.name + ": " + str(time_taken))
def get_time_in_sec(self):
return int(round(time.time() * 1000))
def test_list_index_func(range_num):
lis = [1,2,3,4,5]
with TimeChecker('Process 1') as tim:
for i in range(range_num):
lis.index(4)
test_list_index_func(1000)
test_list_index_func(10000)
test_list_index_func(100000)
test_list_index_func(1000000)
print("Time: O(n)")
【讨论】:
这段代码无法证明list.index
在线性时间内运行。它没有比较 list.index
在不同的输入大小上运行需要多长时间,但它只是多次运行 list.index
。即使你在计算 1+1,如果你计算 1+1 一千次,它所花费的时间是计算一次的 1000 倍。为了确保这是真的,我用二进制搜索测试了你的代码,应该是 O(log n),访问列表的元素应该是 O(1)。自然,他们俩每次调用test_list_index_func
花费的时间都增加了 10 倍,这是线性增长,这是不正确的。【参考方案2】:
上面提供的文档没有涵盖 list.index()
据我了解,list.index 是 O(1) 操作。 如果您想了解更多,这里有一个链接。 https://www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt
【讨论】:
你错了。您的链接所指的“索引”与 python.org wiki 中的 Get Item 相同。您可以在cpython source code 中看到 index 方法正在对列表进行 O(n) 搜索。【参考方案3】:这是 O(n),也请查看:http://wiki.python.org/moin/TimeComplexity
本页记录了当前 CPython 中各种操作的时间复杂度(又名“Big O”或“Big Oh”)。其他 Python 实现(或 CPython 的旧版本或仍在开发中的版本)可能具有稍微不同的性能特征。但是,通常可以安全地假设它们的速度不会超过 O(log n) 的一个因子...
【讨论】:
只是补充一下,因为索引算法可以应用于list
或其他数据结构,它被实现为线性搜索因此O(n)
。
您是否知道是否有特定原因没有将其实现为二进制搜索?这听起来并不过分复杂,但效率会更高。
无法保证列表已排序,因此二进制搜索不起作用
你分享的文档,获取列表项是O(1)。
如果 binary=True
或 sorted=True
是一个可以提供的论据,那就太好了【参考方案4】:
试试这个代码,它会帮助你得到 lis.index 操作符的执行时间。
import timeit
lis=[11,22,33,44,55,66,77]
for i in lis:
t = timeit.Timer("lis.index(11)", "from main import lis")
TimeTaken= t.timeit(number=100000)
print (TimeTaken)
【讨论】:
【参考方案5】:对于线性搜索(例如,list.index),任何列表实现都将具有 O(n) 复杂度。虽然也许有一些古怪的实现会做得更糟......
您可以通过使用不同的数据结构(例如有序列表或集合)来提高查找复杂性。这些通常用二叉树实现。然而,这些数据结构对它们包含的元素施加了限制。在二叉树的情况下,元素需要是可排序的,但查找成本下降到 O(log n)。
如前所述,在此处查看标准 Python 数据结构的运行时成本: http://wiki.python.org/moin/TimeComplexity
【讨论】:
【参考方案6】:根据上述文档:
list.index(x)
返回列表中第一个值为 x 的项目的索引。 如果没有这样的项目是错误的。
这意味着搜索。您实际上是在执行x in s
,但不是返回True
或False
,而是返回x
的索引。因此,我会选择 O(n) 的 listed time complexity。
【讨论】:
以上是关于Python 中 list.index(x) 的复杂性的主要内容,如果未能解决你的问题,请参考以下文章
Python 的 list.index() 函数,当没有找到时不会抛出异常