【问题标题】:Space Complexity of Python List Slices [duplicate]Python列表切片的空间复杂度
【发布时间】:2018-12-02 19:51:50
【问题描述】:

我很难理解 Python 列表切片的空间复杂性。

对于类似的东西

arr[2:] = arr[2:][::-1]

是为切片分配了新空间(就像在字符串中所做的那样,因为它们是不可变的)还是在同一个数组上完成了操作?

例如:

ans = [i+1 for i in range(n)]

for i in range(k):
    ans[i:] = ans[i:][::-1]

空间复杂度是多少?它会与 ans 是字符串时不同还是相同,例如ans = '12345...n'

【问题讨论】:

  • 回答您的第一个问题,this might help
  • 将切片赋值给一个变量,检查并比较id(...)s。
  • @Matos 很酷的发现,另一个 Q 的“简短答案”完全回答了这个问题。投票结束。
  • 链接的问题根本不关心空间复杂性或就地突变。投票支持重新开放。

标签: python string python-3.x list


【解决方案1】:

Python 严格遵守可能的副作用。就语言而言,就地执行任何操作都是不正确的

您的操作

 arr[2:] = arr[2:][::-1]

是三个独立的切片操作:

  • arr[2:]arr所有元素(但前两个)创建一个新列表。
  • ...[::-1]...所有元素 创建一个新的反向列表。
  • arr[2:] = ...arr所有元素(除了前两个)替换为...

每个切片操作基本上相当于一个原始的 O(n) 复制操作。由于只复制引用,因此元素的大小或类型无关紧要。

在您的完整示例中,这相当于一个 O(k) 循环中的三个 O(n) 切片操作:

ans = [i+1 for i in range(n)]   # O(n)
for i in range(k):              # O(k)
    ans[i:] = ans[i:][::-1]     # O(n)

总的来说,时间复杂度为 O(nk)。空间复杂度仅为 O(n),因为临时切片可以立即回收。你基本上得到了初始列表,加上一些临时副本。


它与ans 是一个字符串时会不同还是相同,比如ans = '12345...n'

操作的复杂性没有改变 - 它们仍然是相同的原始操作。

实际上,CPython 实现会欺骗某些对象。例如,+=inplace mutation for strings with refcount 1,即使字符串是不可变的。但是,这不适用于您的切片使用情况。

一般来说,依赖内置优化对于 Python 来说是个坏主意。


如果您担心空间问题,请从编写精简代码开始。例如,ans[i:][::-1] 应该只是 ans[i::-1]。仅此一项就将所需的临时空间减半。

【讨论】:

    【解决方案2】:

    简而言之,每个列表切片操作都涉及制作相关对象引用的副本(而不是对象本身)。

    在你的例子中:

    • arr[2:] 从索引 2 开始复制存储在 arr 中的对象引用,并将它们放入一个未命名的新列表(我将其称为 L1)。
    • [::-1] 复制L1 中的对象引用,并以相反的顺序将它们放入一个未命名的新列表(我将其称为L2)。
    • arr[2:] = ... 将存储在 arr 中的对象引用替换为存储在 L2 中的对象引用。

    值得注意的是,这一切都无法保证。这正是 CPython 目前所做的。

    一些相关的功能是:

    • list_slice - 简单切片(无步幅)
    • list_subscript - 下标公司扩展切片(有步幅)
    • list_ass_slice - 简单的切片分配(无步幅)
    • list_ass_subscript - 下标赋值,公司。使用扩展切片

    看看list的实现:https://github.com/python/cpython/blob/master/Objects/listobject.c

    那里有一些有趣的花絮,例如code that protects against a[::-1] = a

    【讨论】:

      猜你喜欢
      • 2016-03-25
      • 2012-12-16
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      • 2023-02-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多