一尘不染

迭代字符串的时间复杂性实际上是O(n ^ 2)还是O(n)?

algorithm

我正在处理CTCI之外的问题。

第1章的第三个问题是您采用了诸如

'Mr John Smith '

并要求您将中介空间替换为%20

'Mr%20John%20Smith'

作者使用Python提供了此解决方案,称其为O(n):

def urlify(string, length):
    '''function replaces single spaces with %20 and removes trailing spaces'''
    counter = 0
    output = ''
    for char in string:
        counter += 1
        if counter > length:
            return output
        elif char == ' ':
            output = output + '%20'
        elif char != ' ':
            output = output + char
    return output

我的问题:

我了解这是从左到右扫描实际字符串方面的O(n)。但是Python中的字符串不是一成不变的吗?如果我有一个字符串,并且用+运算符向它添加了另一个字符串,它是否分配了必要的空间,复制了原始字符串,然后复制了追加字符串?

如果我有一个n长度为1 的字符串集合,则需要:

1 + 2 + 3 + 4 + 5 + ... + n = n(n+1)/2

还是 O(n ^ 2)时间 ,是吗?还是我在Python处理附加方式方面弄错了?

或者,如果您愿意教我如何钓鱼:我将如何亲自找到答案?我尝试向Google寻求官方消息一直没有成功。我发现https://wiki.python.org/moin/TimeComplexity,但这在字符串上没有任何内容。


阅读 159

收藏
2020-07-28

共1个答案

一尘不染

在CPython(Python的标准实现)中,有一个实现细节,使该通常为O(n)的形式在字节码评估循环调用++=使用两个字符串操作数的代码中实现。如果Python检测到left参数没有其他引用,它将调用realloc来尝试通过调整字符串的大小来避免复制。这不是您应该依靠的东西,因为它是一个实现细节,并且因为如果realloc最终需要频繁移动字符串,则性能无论如何都会降低到O(n
^ 2)。

在没有怪异的实现细节的情况下,由于涉及的二次复制量,该算法为O(n ^ 2)。这样的代码仅在具有可变字符串的语言(例如C
)中才有意义,甚至在您想使用的C 中也是如此+=

2020-07-28