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=Truesorted=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,但不是返回TrueFalse,而是返回x 的索引。因此,我会选择 O(n) 的 listed time complexity。

【讨论】:

以上是关于Python 中 list.index(x) 的复杂性的主要内容,如果未能解决你的问题,请参考以下文章

Python 的 list.index() 函数,当没有找到时不会抛出异常

numpy 相当于 list.index [重复]

index在python中的用法

index在python中的用法

在python中处理list.index(可能不存在)的最佳方法?

python列表,元组