【问题标题】:Complexity of list.index(x) in PythonPython 中 list.index(x) 的复杂性
【发布时间】: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。

标签: python algorithm list big-o performance


【解决方案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

      【讨论】:

        猜你喜欢
        • 2021-07-27
        • 2019-01-18
        • 2018-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-02
        相关资源
        最近更新 更多