python - 在 python 中获取子字符串是 O(n) 操作吗?
问题描述
在 C++ 中,如果我要从字符串中删除第一个字符,它看起来像:
string s = "myreallylongstring";
s = s.substr(1);
这将是 O(1)。[如果我错了请纠正我]
然而,在 Python 的“不可变字符串”世界中,这段代码是否在 O(n) 中运行?
s = "myreallylongstring"
s = s[1:]
如果我改用字符列表会更快吗?
解决方案
切片 Python 中的任何内置类型(除了memoryview
)是O(n)
一般情况(主要例外是不可变实例的完整切片,它通常返回原始实例而不复制它,因为它不是必需的)。
一个list
字符无济于事;list
从 a is的开头删除一个字符O(n)
(它必须将其上方的所有内容复制到一个插槽中)。collections.deque
可以想象,A可以改进 big-O(它们可以O(1)
从任一端弹出),但它也会比字符串消耗更多的内存和更多的碎片内存。
对于除了最大的字符串之外的所有字符串,即使O(n)
效率低下,您通常也可以,所以除非您实际进行了分析并发现它是导致问题的原因,否则我会坚持切片并顺其自然。
也就是说,您对 C++ 的看法是错误的;s = s.substr(1)
与 Python 的s = s[1:]
. 它们最终都复制了整个字符串并保存了第一个字符,C++ move 分配回原始字符串,而 Python 用新对象替换了与旧对象的原始名称绑定(功能上非常相似的操作)。s.substr(1)
甚至没有使用std::string
's 的可变性功能;s.erase(0, 1)
实际上会就地擦除,改变原始字符串,但这仍然是O(n)
因为所有其他字符都必须复制到先前被删除字符占用的空间中(没有std::string
我知道的实现允许存储从字符串开头的偏移量以查找真实数据,指向数据的指针始终指向第一个分配的字节)。
推荐阅读
- php - 自动将数据从 csv 导入到带有验证的 mysql 表
- java - 不能在片段外调用函数 volley?
- java - 如何用我自己创建的键盘替换普通的 InputMethod/Keyboard?
- c# - 当 Selenium ChromeDriver 的 URL 改变时触发一个事件
- visual-studio - 亚音速 ORM 发生器输出中文
- airflow - 使用代码,如何更新气流变量?
- android - 尝试使用 SQlite 创建表时出错
- delphi - 自定义控制感应加速字符
- azure - 我可以将现有的 Azure Redis 缓存从传统的经典 Azure 订阅移动到 CSP 吗?
- runtime - 什么是运行时单个循环,但它运行了 n 次?