Java 为什么StringBuilder.append的时间复杂度为O(1)

Java 为什么StringBuilder.append的时间复杂度为O(1),java,stringbuilder,Java,Stringbuilder,通过摊销分析,我们知道使用StringBuilder#append方法插入N需要O(N)时间。但这是我迷路的地方。考虑下面的代码:输入字符串是用户的输入字符串。 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

通过摊销分析,我们知道使用
StringBuilder#append
方法插入
N
需要
O(N)
时间。但这是我迷路的地方。考虑下面的代码:<代码>输入字符串是用户的输入字符串。

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
}
for(int i=0;i
由于
append()
将输入字符串复制到
StringBuilder
N
次的末尾,因此这是否具有时间复杂度
O(inputString.length*N)
?为什么我们认为<代码>附录()>代码>采用<代码> O(1)< /代码>时间复杂度,而应该被认为是“代码> O(输入字符串?长度)< /COD>?< /P> 几乎在我检查的所有地方,它都被认为是
O(1)
,例如

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

为什么我们认为AppEnter()需要O(1)时间复杂度,而它应该被视为O(输入字符串?长度)?< /P> 追加单个字符时为O(1)。StringBuilder就像ArrayList。附加单个项目时,成本为O(1)。追加字符串类似于调用addAll()——成本与字符串的长度/添加的项目数成比例


看来你对一切都理解正确。问题在于,人们在讨论Big-O性能时往往草率行事。这是地方病

复杂性分析更像是一门艺术。如果输入字符串长度是输入数据中的可变因子,并且可以无限大,那么您应该将其考虑在内。如果您所陈述的问题/算法给出了输入字符串长度的上限,那么它是一个常数因子。但请注意,真正的机器几乎总是有长度限制,因为存储不是无限的——Java将字符串限制为2^31-1个字符,所以从技术上讲,它总是O(1)。这取决于你想从哪个角度来分析你的算法。@ErwinBolwidt每一个计算机系统都是有限的。在复杂度分析中,我们不承认这一点,因为它使每个算法都成为O(1)。提起这件事会分散注意力。@JohnKugelman不,这不是在转移注意力。这是最基本的。没有进一步限定的Big-O是指N趋于无穷大。如果N不是无穷大,它是一个常数因子。在实际应用中,常数因子是否足够接近无穷大是很重要的。如果一个CPU可以做一个最大可能的数据长度的内存拷贝,而不是做一个固定的时间操作,那么你应该考虑O(1)。如果差异大得多,你应该考虑O(n)。然而,这里更重要的是,问题是否限制了输入的长度。您说过字符串的最大长度是2^31-1,所以从技术上讲,O(n)字符串算法是O(1)。这个问题没有提到对
inputString
大小的任何限制,所以我不知道为什么会有这样的想法。你可以用任何大O分析中的任何变量来做这件事。“嗯,如果数组的大小是有界的,那么从技术上讲O(n logn)排序是O(1)。哦,如果链表的大小是有界的,那么从技术上讲O(n)搜索是O(1)。哦,还有…”为什么说这些话?它们是毫无意义的陈述。A)我不需要具体的例子,因为O符号是理论的,所以我们处理理论模型。B) 具体的世界示例64位数字是由8位数字组成的8元素数组。复制一个字节需要一个周期复制一个qword需要一个周期。你不能对底层函数如何工作做出假设。在什么理论模型中复制一个大小为no(1)的数组?这就是N/k,其中k是可以复制的块大小的常数因子。这仍然是O(n)你缺少的一点算法效率与现实世界的性能无关,它完全是理论上的。对于O,符号k=无穷大是有效的。数组副本可以只是指针更改,也可以是使用仓鼠进行的逐点传输。当设计一个我们不知道也不知道的算法时,它可能是冰河时期的,也可能是瞬间的,所以它是不相关的。我重复一遍,你不能对底层函数的工作方式做出假设。