【问题标题】:Does insert at the end of a list have O(1) time complexity?在列表末尾插入是否具有 O(1) 时间复杂度?
【发布时间】:2020-02-04 04:53:55
【问题描述】:

列表末尾的appendinsert 有区别吗?列表末尾的insert 是常数时间操作吗?

nums = [1, 2, 3]
nums.append(4)  # Time complexity: O(1)
nums.insert(len(nums), 5)  # Time complexity: O(?)

根据 Python Wiki 中的 TimeComplexity 文章,append 的平均情况为 O(1),而 insert 的平均情况为 O(n)。但是,在Python tutorial 中提到:

...和a.insert(len(a), x) 等价于a.append(x)

我不确定“等效”是否意味着“功能等效”或“时间复杂度等效”。有人知道吗?

【问题讨论】:

  • 时间复杂度文章在一般情况下是正确的,因为insert 并不总是位于列表的末尾。
  • @ParitoshSingh 是的,我知道。我的问题是insert 的时间复杂度在插入到列表末尾的特殊情况下是否为 O(1)。
  • insert 中的n 实际上是需要移动的元素数量。如果不需要移动元素,则可以忽略该操作。在任何情况下,它仍然是 O(n) 的时间复杂度,因为大 O 表示法实际上并没有测量一些模糊甚至精确的时间复杂度,更多的是描述它们的运行时间/空间需求如何随着输入大小的增长而增长. More details at wikipedia.
  • 换句话说,list.insert 的平均值总是 O(n),并且 big-O 表示法不会对边缘情况(例如最好或最坏的情况;在您的情况下,可以简化为简单的操作 list.append)。
  • 更迂腐,append 摊销 O(1),而不是 O(1)。见this thread

标签: python list time-complexity cpython


【解决方案1】:

插入列表的最差时间复杂度是O(n-i),其中n 是列表的长度,i 是您要插入的索引。

所以如果你在最后一个索引处插入,那就是O(1)

这里有一篇文章可以帮助你更好地理解:

https://yourbasic.org/algorithms/time-complexity-arrays/.

【讨论】:

    【解决方案2】:

    关于“功能等效”,我会说这是真的,因为它们都会为 Python 列表产生完全相同的结果。

    在这种情况下,时间复杂度与 list 相当,因为 list insert() 实现通过移动索引后面的元素来工作,因此如果新元素插入到列表的末尾,则不会移动执行操作。 这可以通过查看list insert 的实现来验证。 在插入实现行248-251中,

    for (i = n; --i >= where; )
            items[i+1] = items[i];
    Py_INCREF(v);
    items[where] = v;
    

    同时,在list append的执行中

    Py_INCREF(v);
    PyList_SET_ITEM(self, n, v);
    

    PyList_SET_ITEMdefined 如:

    #define PyList_SET_ITEM(op, i, v) (((PyListObject *)(op))->ob_item[i] = (v))
    

    因此,由于where 等于n,在这种情况下是列表大小,for 循环立即终止。之后的几行几乎是等效的,基本上只是将元素插入到数组中。

    因此,可以说,对于这种情况,摊销时间复杂度是相同的,即 O(1)

    【讨论】:

      猜你喜欢
      • 2020-08-18
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      • 2020-09-11
      • 2019-11-09
      • 2017-07-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多