为什么python的list.append()方法的时间复杂度是O(1)?
Why is the time complexity of python's list.append() method O(1)?
如 TimeComplexity 的文档所示,Python 的 list
类型是使用数组实现的。
因此,如果正在使用数组并且我们进行了一些追加,最终您将不得不重新分配 space 并将所有信息复制到新的 space.
毕竟,最坏的情况怎么可能是 O(1)?
如果您查看所链接文档中的脚注,您会发现其中包含一个警告:
These operations rely on the "Amortized" part of "Amortized Worst
Case". Individual actions may take surprisingly long, depending on the
history of the container.
使用 amortized analysis,即使我们不得不偶尔执行昂贵的操作,当您将它们视为一个序列而不是单独考虑时,我们可以获得 'average' 操作成本的下限。
因此,任何单独的操作都可能非常昂贵 - O(n) 或 O(n^2) 或更大的东西 - 但由于我们知道这些操作很少见,我们保证 O(n)操作可以在 O(n) 时间内完成。
它的摊销时间为 O(1),而不是 O(1)。
假设列表保留大小为 8 个元素,当 space 用完时它的大小加倍。你想推送 50 个元素。
前8个元素压入O(1)。
第 9 个触发重新分配和 8 个副本,然后是 O(1) 推送。
接下来的 7 个推入 O(1)。
第十七次触发重新分配和 16 个副本,然后是 O(1) 推送。
接下来的 15 个推入 O(1)。
第 33 个触发重新分配和 32 个副本,然后是 O(1) 推送。
接下来的 17 个推入 O(1).
所以所有推送的复杂度都是 O(1),我们在 O(1) 时有 56 个副本,在 O(n) 时有 3 个重新分配,n = 8、16 和 32。请注意,这是一个几何级数,渐近等于 O(n),其中 n = 列表的最终大小。这意味着将 n 个对象推入列表的整个操作是 O(n)。如果我们 摊销 每个元素,它是 O(n)/n = O(1)。
这很容易。
我们可以通过累加将 n 个元素添加到 arraylist 中的总时间除以 n 来计算。
首先,我们需要重定位log(n)次,每次重定位翻倍2.So我们有一个比例级数,比例为2,长度为log(n)。
比例级数的和是a(1-r^n)/(1-r)
所以搬迁的总时间是(1-n)/(1-2)=n
时间复杂度为 n/n=1.
如 TimeComplexity 的文档所示,Python 的 list
类型是使用数组实现的。
因此,如果正在使用数组并且我们进行了一些追加,最终您将不得不重新分配 space 并将所有信息复制到新的 space.
毕竟,最坏的情况怎么可能是 O(1)?
如果您查看所链接文档中的脚注,您会发现其中包含一个警告:
These operations rely on the "Amortized" part of "Amortized Worst Case". Individual actions may take surprisingly long, depending on the history of the container.
使用 amortized analysis,即使我们不得不偶尔执行昂贵的操作,当您将它们视为一个序列而不是单独考虑时,我们可以获得 'average' 操作成本的下限。
因此,任何单独的操作都可能非常昂贵 - O(n) 或 O(n^2) 或更大的东西 - 但由于我们知道这些操作很少见,我们保证 O(n)操作可以在 O(n) 时间内完成。
它的摊销时间为 O(1),而不是 O(1)。
假设列表保留大小为 8 个元素,当 space 用完时它的大小加倍。你想推送 50 个元素。
前8个元素压入O(1)。 第 9 个触发重新分配和 8 个副本,然后是 O(1) 推送。 接下来的 7 个推入 O(1)。 第十七次触发重新分配和 16 个副本,然后是 O(1) 推送。 接下来的 15 个推入 O(1)。 第 33 个触发重新分配和 32 个副本,然后是 O(1) 推送。 接下来的 17 个推入 O(1).
所以所有推送的复杂度都是 O(1),我们在 O(1) 时有 56 个副本,在 O(n) 时有 3 个重新分配,n = 8、16 和 32。请注意,这是一个几何级数,渐近等于 O(n),其中 n = 列表的最终大小。这意味着将 n 个对象推入列表的整个操作是 O(n)。如果我们 摊销 每个元素,它是 O(n)/n = O(1)。
这很容易。
我们可以通过累加将 n 个元素添加到 arraylist 中的总时间除以 n 来计算。
首先,我们需要重定位log(n)次,每次重定位翻倍2.So我们有一个比例级数,比例为2,长度为log(n)。
比例级数的和是a(1-r^n)/(1-r) 所以搬迁的总时间是(1-n)/(1-2)=n 时间复杂度为 n/n=1.