【问题标题】:Why StringBuilder.append time complexity is O(1)为什么 StringBuilder.append 时间复杂度是 O(1)
【发布时间】:2019-11-09 22:47:14
【问题描述】:

通过摊销分析,我们知道N 插入StringBuilder#append 方法需要O(N) 时间。但这是我迷路的地方。考虑一下inputString 是来自用户的输入字符串。

for (int i = 0; i < N; i++) {
   s.append(inputString); 
   // where s is an empty StringBuilder object at the beginning 
   // and inputString is the string that is taken from the user
}

这是否应该具有O(inputString.length * N) 的时间复杂度,因为append() 将输入字符串复制到StringBuilder 的末尾N 次?为什么我们认为append() 需要O(1) 的时间复杂度,而它应该被认为是O(inputString.length)

我检查的几乎所有地方都被视为O(1),例如https://quora.com/What-is-the-complexity-of-Java-StringBuffer-append 以及What is the complexity of this simple piece of code?

【问题讨论】:

  • 复杂性分析更像是一门艺术。如果您的输入字符串长度是输入数据中的可变因素,并且可以达到无穷大,那么您应该考虑到它。如果您陈述的问题/算法给出了输入字符串长度的上限,那么它是一个常数因子。但请注意,真实机器几乎总是对长度有限制,因为存储不是无限的——Java 将字符串限制为 2^31-1 个字符,所以从技术上讲它总是 O(1)。这取决于您要从哪个角度分析您的算法。
  • @ErwinBolwidt 每个计算机系统都是有限的。我们在复杂性分析中不承认这一点,因为它使 every 算法为 O(1)。提起它会分散注意力。
  • @JohnKugelman 不,这不是红鲱鱼。这是基本的。没有进一步限定的 Big-O 正在谈论 N 趋于无穷大。如果 N 不是无穷大,它是一个常数因子。对于实际目的,常数因子是否足够接近无穷大很重要。如果 CPU 可以对数据的最大可能长度进行内存复制,而只需要进行恒定时间操作所需的时间,那么您应该将其视为 O(1)。如果差异更大,则应考虑 O(n)。然而,这里更重要的是问题是否限制了输入的长度。
  • 你说字符串的最大长度是 2^31-1,所以技术上 O(n) 字符串算法是 O(1)。这让人分心。
  • 这个问题没有提到对inputString 大小的任何限制,所以我不知道为什么会被想象。您可以在任何 Big-O 分析中使用任何变量来做到这一点。 “好吧,如果数组的大小是有界的,那么技术上 O(n log n) 排序就是O(1)。哦,如果一个链表的大小是有界的,那么从技术上讲 O(n) 搜索是 O(1)。哦,还有……”为什么要说那些话?它们是毫无意义的陈述。

标签: java stringbuilder


【解决方案1】:

这是否应该具有 O(inputString.length * N) 的时间复杂度,因为 append() 将输入字符串复制到 StringBuilder 的末尾 N 次?

是的。

为什么我们认为 append() 需要 O(1) 时间复杂度,而它应该被认为是 O(inputString.length)?

添加单个字符时是 O(1)。 StringBuilder 类似于 ArrayList。当您附加单个项目时,成本为 O(1)。添加字符串就像调用 addAll() 一样——开销与字符串的长度/要添加的项目数成正比。

您似乎正确理解了所有内容。问题是人们在讨论 Big-O 性能时经常马虎。这是地方病。

【讨论】:

  • A) 我不需要具体的例子,因为 O 表示法是理论上的,所以我们处理理论模型。 B)具体世界示例 64 位数字是 8 位数字的 8 元素数组。复制 1 个字节需要 1 个周期 复制一个 qword 需要 1 个周期。您不能对底层函数的工作方式做出假设。
  • 在什么理论模型中复制一个大小为 N O(1) 的数组?
  • 这只是使其成为 n/k,其中 k 是可以复制的块有多大的常数因子。那仍然是 O(n)
  • 您错过了要点算法效率与现实世界的性能无关,它完全是理论上的。对于 O 表示法 k = 无穷大是有效的。数组副本可能只是指针更改,也可能是使用仓鼠一点一点地传输。它可能是缓慢的,也可能是瞬时的,在设计算法时,我们不知道也无法知道,所以它是无关紧要的。我再说一遍,你不能对底层函数的工作方式做出假设。
猜你喜欢
  • 2017-09-01
  • 2020-09-11
  • 2021-01-01
  • 1970-01-01
  • 2019-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多