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

2025-02-17 09:24:00
admin
原创
61
摘要:问题描述:我正在解决 CTCI 之外的一个问题。第一章的第三个问题要求你取一个字符串,例如'Mr John Smith '并要求您将中间空格替换为%20:'Mr%20John%20Smith'作者在 Python 中提供了这个解决方案,称之为 O(n):def urlify(string, length): ...

问题描述:

我正在解决 CTCI 之外的一个问题。

第一章的第三个问题要求你取一个字符串,例如

'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,但这里没有任何关于字符串的内容。


解决方案 1:

在 CPython(Python 的标准实现)中,有一个实现细节通常使此操作复杂度为 O(n),在字节码求值循环调用的代码中实现+,或+=使用两个字符串操作数。如果 Python 检测到左侧参数没有其他引用,它会调用realloc以尝试通过就地调整字符串大小来避免复制。您永远不应该依赖这一点,因为它是一个实现细节,并且如果realloc最终需要频繁移动字符串,性能无论如何都会降低到 O(n^2)。

如果没有奇怪的实现细节,由于涉及二次方的复制量,该算法的复杂度为 O(n^2)。这样的代码只有在具有可变字符串的语言(如 C++)中才有意义,即使在 C++ 中,您也希望使用+=

解决方案 2:

作者依赖的优化恰好在这里,但并不明确可靠。strA = strB + strC通常是O(n),使得函数O(n^2)。但是,确保整个过程是相当容易的O(n),使用数组:

output = []
    # ... loop thing
    output.append('%20')
    # ...
    output.append(char)
# ...
return ''.join(output)

简而言之,该append操作是摊销的 ,(尽管您可以通过预先分配数组到正确的大小来O(1)使其变得强大),从而使循环。O(1)`O(n)`

然后也是joinO(n)但是没关系因为它在循环之外。

解决方案 3:

我在“Python Speed > 使用最佳算法和最快工具”上找到了这段文字:

字符串连接最好使用''.join(seq)which来完成O(n)。相反,使用'+'or'+='运算符可能会导致一个O(n^2)过程,因为可能会为每个中间步骤构建新的字符串。CPython 2.4 解释器在一定程度上缓解了这个问题;然而,''.join(seq)仍然是最佳实践

解决方案 4:

对于未来的访问者:由于这是一个 CTCI 问题,因此这里不需要任何有关学习urllib包的参考,特别是根据 OP 和书籍,这个问题是关于数组和字符串的。

这是一个更完整的解决方案,受到@njzk2 的伪启发:

text = 'Mr John Smith'#13 
special_str = '%20'
def URLify(text, text_len, special_str):
    url = [] 
    for i in range(text_len): # O(n)
        if text[i] == ' ': # n-s
            url.append(special_str) # append() is O(1)
        else:
            url.append(text[i]) # O(1)

    print(url)
    return ''.join(url) #O(n)


print(URLify(text, 13, '%20'))
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2525  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1542  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Filestage、Xebrio、Kintone、Monday、Celoxis、Backlog、BubblePPM、Plutio、Scoro。在当今快速变化的商业环境中,项目管理系统的选择成为企业成功的关键因素之一。许多企业在选购项目管理系统时,常常面临功能复杂、...
项目管理系统   0  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Plutio、Kantata、Kintone、LiquidPlanner、Motion、Smartsheet、Targa、QuickBase、Hive。在当今快节奏的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而,面对市...
开源项目管理软件   15  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Scoro、Wekan、Hubstaff、Kintone、Wrike、Filestage、Trello、Airtable、Paymo。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时常常面临诸多挑战,如任务分...
项目管理系统   7  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用