通过char添加Java字符串char的空间复杂性

时间:2018-07-01 20:43:01

标签: java string complexity-theory string-concatenation space-complexity

在通过“加法”的循环逐个字符地构建Java String char时,可以发现执行此操作的时间复杂度很差:它是二次的 O(n^2)时间。但是,我想知道通过循环“逐个字符地添加”一个字符串的空间复杂性是否也很差。

这是一个程序的最小示例,该程序通过具有秒表计时功能的逐个字符添加来执行构建String的操作。我在下面显示的结果清楚地显示出二次曲线:

/**Create a String of n 'A's char-by-char.
 * @param n Number of 'A's to be appended
 * @return The finished string
 */
public static String appendString(int n) {
    String str = "";
    // Timed run starts here
    long t = System.currentTimeMillis();
    // String concatenation occurs here
    for (int k = 0; k < n; k++)
        str += "A";
    t = System.currentTimeMillis() - t;
    // Timed run ends
    System.out.printf("%d\t%d\n", n, t);
    return str;
}

尽管我可以获得程序的时间复杂度,但我想知道构建逐个字符的字符串的空间复杂度是什么?

首选解决内存管理的详细答案。 (我怀疑这也是平方的,因为字符串是不可变的,并且每次您必须为不断增长的字符串分配新的内存时就可以使用

注意:这不是String concatenation complexity in C++ and Java的重复,因为它不能解决空间复杂性。我特别要求详细的空间复杂度分析。

2 个答案:

答案 0 :(得分:2)

您的代码效率很低,因为,将创建​​一个隐式StringBuilder来在循环中添加单个字符。这个

for (int k = 0; k < n; k++)
    str += "A";

等价于

for (int k = 0; k < n; k++)
    str = new StringBuilder(str).append("A").toString();

您可以通过使用单个StringBuilder来极大地提高空间(和时间)性能(并且可以明确调整其大小)。喜欢,

StringBuilder sb = new StringBuilder(n);
for (int k = 0; k < n; k++)
    sb.append("A");
String str = sb.toString();

,在Java 8+中,您可以使用生成器并将其限制为n次并进行收集。喜欢,

return Stream.generate(() -> "A").limit(n).collect(Collectors.joining());

答案 1 :(得分:1)

它使用二次空间。或者,而是分配了二次空间,因为循环的每次迭代(至少在JIT不会巧妙执行的代码中)都会分配一个新的char数组:

new char[1]
new char[2]
new char[3]
// Etc.

之所以具有二次时间性能,是因为将字符串复制到了这些越来越大的数组中。