【问题标题】:What is the runtime complexity of python list functions?python列表函数的运行时复杂度是多少?
【发布时间】:2018-09-20 04:33:29
【问题描述】:

我正在编写一个看起来像这样的python函数

def foo(some_list):
   for i in range(0, len(some_list)):
       bar(some_list[i], i)

所以它被调用了

x = [0, 1, 2, 3, ... ]
foo(x)

我曾假设列表的索引访问是 O(1),但惊讶地发现对于大型列表,这比我预期的要慢得多。

那么,我的问题是python列表是如何实现的,下面的运行时复杂度是多少

  • 索引:list[x]
  • 从最后弹出:list.pop()
  • 从头弹出:list.pop(0)
  • 扩展列表:list.append(x)

为了额外的信用,拼接或任意弹出。

【问题讨论】:

    标签: python complexity-theory


    【解决方案1】:

    a very detailed table on python wiki 可以回答您的问题。

    但是,在您的特定示例中,您应该使用enumerate 来获取循环内可迭代的索引。像这样:

    for i, item in enumerate(some_seq):
        bar(item, i)
    

    【讨论】:

    • 原谅我的无知,但该页面上pop() 的复杂性在哪里?
    • @Zaz,没有索引的 pop() 是 O(1),有索引,例如列表中的第一个,它是 O(n)。因为您需要获取项目 O(1) 然后将其删除。后者需要 O(n) 时间来安排列表中的所有其他项目。更多信息在这里:ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt
    【解决方案2】:

    答案是“未定义”。 Python 语言没有定义底层实现。以下是您可能感兴趣的邮件列表主题的一些链接。

    另外,编写循环的更 Pythonic 的方式是:

    def foo(some_list):
       for item in some_list:
           bar(item)
    

    【讨论】:

    • 糟糕,我知道我的方法比 Pythonic 要少一些。对于我的循环,我需要该项目以及索引。有什么好的方法吗? (编辑我的问题)
    【解决方案3】:

    列表确实是 O(1) 的索引 - 它们被实现为具有比例过度分配的向量,因此按您的预期执行。您发现此代码比您预期慢的可能原因是对“range(0, len(some_list))”的调用。

    range() 创建一个指定大小的新列表,所以如果 some_list 有 1,000,000 个项目,您将在前面创建一个新的百万项目列表。这种行为在 python3 中发生了变化(范围是一个迭代器),python2 的等效项是xrange,或者更适合您的情况,enumerate

    【讨论】:

      【解决方案4】:

      如果您需要索引和值,请使用枚举:

      for idx, item in enumerate(range(10, 100, 10)):
          print idx, item
      

      【讨论】:

        【解决方案5】:

        Python 列表实际上只是数组。因此,

        索引需要 O(1)

        根据文档,对于 pop 并再次追加,它应该是 O(1)

        查看以下链接了解详情:

        http://dustycodes.wordpress.com/2012/03/31/pythons-data-structures-complexity-analysis/

        【讨论】:

          猜你喜欢
          • 2019-06-08
          • 1970-01-01
          • 2014-04-19
          • 1970-01-01
          • 1970-01-01
          • 2011-11-11
          • 2013-01-04
          • 1970-01-01
          相关资源
          最近更新 更多