Python - del my_list [:]的Big-O?

时间:2017-05-24 03:36:14

标签: python

del my_list [:]的大O是什么?此命令会删除列表中的所有元素。我的理解是它将是O(n)。 n是列表的长度。

因此,此代码的大O将是bigO(n ^ 2),对吗?

请注意,这不是针对学校的,而是针对我在面试时练习的理解。

from copy import deepcopy
class Solution:
    # @param A : list of integers
    # @return an integer
    def removeDuplicates(self, A):
        copy_array = deepcopy(A)
        del A[:]

        for j in copy_array:
            if j in A:
                pass
            else:
                A.append(j)

        return len(A)

3 个答案:

答案 0 :(得分:5)

此处del不影响big-O,循环为nj in A测试为n,因此嵌套循环为{{ 1}}; O(n**2)del,但它不是循环的一部分,因为它是较低的工作顺序,所以会被忽略。

附注:对此O(n)解决方案是使用collections.OrderedDict进行重复数据删除,保留顺序,使方法的主体只是:

O(n)

答案 1 :(得分:2)

def removeDuplicates(self, A):
    copy_array = deepcopy(A)        --> O(N)
    del A[:]                        --> O(N)

    for j in copy_array:            --> O(N)
        if j in A:                  --> O(N)
            pass
        else:
            A.append(j)             --> O(1)

    return len(A)                   --> O(1)

复杂度为2O(N)+ O(N)* O(N)+ O(1)= O(2N + N ^ 2 + 1)= O(N ^ 2)

答案 2 :(得分:2)

如注释和其他答案中所述,在您的情况下,删除是否为O(n)并不重要,因为这是一次性操作,并且您的循环已经是O(n ^ 2)。

尽管如此,关于del A[:]的问题很有意思且值得解决:

根据Python wiki的page on time complexity,从列表中删除切片确实是O(n)。

但是,由于列表在内部表示为数组,并且[:]上的操作基本上是重新分配整个数组,旧的数组可以在稍后的时间点进行垃圾收集,我认为这可能是这种情况实际上可以在实现中进行优化,以便 del语句本身为O(1),并且旧数组的实际清理延迟算法成本可能仍为O(n)但是,这可能会延迟一些工作,将其从程序中的计算“热点”中删除。

根据下面的第一条评论,Python的主要实现CPython使用引用计数;这意味着del必须实际减少列表中包含的每个项目的引用计数,即O(n)。

然而,PyPy has configurable garbage collection和所有受支持的收集器似乎都基于分代复制方案,确实允许优化。此外,在复制方案中,通常可以忽略包含旧对象的内存而不是正确地解除分配,因此实际的延迟成本实际上可能是 free (在{{1}的意义上声明使下一代复制更便宜,因为原始数组不再需要复制)。为“被忽略”的对象分配的数据可能仍然是清除(事实上PyPy链接表明其代际GC确实这样做了),但由于整个旧的内存空间被清除,我不确定这个空间实际填充了多少很重要。

然而,

注意,需要特殊清理操作的对象,即实现del的对象,是一种特殊情况,而不能只是被“忽略”在分代复制期间,因此取消分配__del__ 的对象数组必须始终为O(n)。链接页面有一些关于如何处理这些对象的细节。