【发布时间】: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