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

2025-02-17 09:24:00
admin
原创
52
摘要:问题描述:我正在解决 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2098  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1460  
  建筑行业正处于数字化转型的关键时期,建筑产品生命周期管理(PLM)系统的实施对于提升项目效率、质量和协同性至关重要。特别是在 2025 年,基于建筑信息模型(BIM)的项目进度优化工具成为众多建筑企业关注的焦点。这些工具不仅能够整合项目全生命周期的数据,还能通过精准的分析和模拟,为项目进度管理提供强大支持。BIM 与建...
plm是什么软件   13  
  PLM系统开发的重要性与现状PLM(产品生命周期管理)系统在现代企业的产品研发、生产与管理过程中扮演着至关重要的角色。它贯穿产品从概念设计到退役的整个生命周期,整合了产品数据、流程以及人员等多方面的资源,极大地提高了企业的协同效率和创新能力。通过PLM系统,企业能够实现产品信息的集中管理与共享,不同部门之间可以实时获取...
国产plm软件   15  
  PLM(产品生命周期管理)系统在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和技术的飞速发展,企业对PLM系统的迭代周期优化需求日益迫切。2025年敏捷认证对项目管理提出了新的要求,其中燃尽图作为一种强大的可视化工具,在PLM系统迭代周期优化中有着广泛且重要的应用。深入探讨这些应用,对于提升企业的项...
plm系统主要干什么的   16  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用