java - Java中字符串重复追加的大O

标签 java big-o stringbuilder

我有一个函数可以获取一个字符串作为原始字符串的重复。我想知道如果我使用 StringBuilder 追加,该函数的 Big O 是什么?是 O(nl) 吗:n 是重复次数,l 是原始字符串的长度?

public String getRepetition(String originalStr, Integer n){
    StringBuilder str = new StringBuilder();
    for(int i = 0; i < n; i++)
        str.append(originalStr);
    return str.toString();
}

与下面的方法相比,哪一种更好?

public String getRepetition(String originalStr, Integer n){
    String str = "";
    for(int i = 0; i < n; i++)
        str += originalStr;
    return originalStr;
}

最佳答案

我不确定为什么其他三个答案都说这两段代码都是 O(n) 。假设 originalStr 不是 "",第一个是 O(n),另一个是 O(n^2)! (这是一个感叹号,而不是阶乘。)他们在 Java 学校的第一天教授这个。 C 程序员得到“在 for 循环的条件下不要使用 strlen”; Java 程序员明白这一点。

String str = "";
for(int i = 0; i < n; i++)
    str += originalStr;

每次循环str都会变得更长。它是i * orinalStr.length()。创建一个新的String(假设没有狂野编译器优化),每次所花费的时间大致与i成正比。

编辑:通常我们会忽略原始字符串的长度。但是,是的,它当然是比例的,所以 O(nstrlen(originalStr)) 和 O(nn*strlen(originalStr)) 。按照惯例,这是单独处理的。

如果我们重写代码而不使用String抽象,也许会更清晰。

public static char[] getRepetition(char[] originalStr, int n) {
    char[] str = {};
    for (int i = 0; i < n; ++i) {
        assert str.length == i * originalStr.length;
        char[] newStr = new char[str.length + originalStr.length];
        for (int j=0; j<str.length; ++j) {
            newStr[j] = str[j];
        }
        for (int j=0; j<originalStr.length; ++j) {
            newStr[str.length+j] = originalStr[j];
        }
        str = newStr;
    }
    return str;
}

(一如既往,我懒得编译代码。在核 react 堆中使用不安全。)

为了搞笑,让我们对第一个实现进行抽象。

public static char[] getRepetition(char[] originalStr, int n) {
    char[] str = new char[16];
    int strLen = 0;
    for (int i = 0; i < n; ++i) {
        assert strLen == i * originalStr.length;
        // ensureCapacity
        if (str.length < strLen + originalStr.length) {
            // The size at least doubles, 
            //   so this happens increasing less often.
            // It wont happen again for approximately
            //   the same number of iterations
            //   as have already happened!
            char[] newStr = new char[Math.min(
                str.length + originalStr.length, // first time safe
                str.length*2 + 2                 // *2 !
            )];
            for (int j=0; j<strLen; ++j) {
                newStr[j] = str[j];
            }
            str = newStr;
        }
        // actual append
        for (int j=0; j<originalStr.length; ++j) {
            str[strLen++] = originalStr[j];
        }
    }
    // toString
    char[] newStr = new char[strLen];
    for (int i=0; j<newStr.length; ++i) {
         newStr[i] = str[j];
    }
    return newStr;
}

关于java - Java中字符串重复追加的大O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53901364/

相关文章:

java - 如何求涉及对数和求和规则的嵌套 for 循环的时间复杂度?

java - StringBuilder的deleteCharAt()函数 "String index out of range : 6 "

java - dom4j.Node 迭代元素映射

java - 如何将数据从jsp传递到servlet?

java - Encog SVM 无法训练

c# - 如何明智地使用 StringBuilder?

java - 不能用Eclipse做StringBuilder

java - 如何在不依赖方法的情况下删除链表末尾的节点?

c++ - 计算排序的复杂度

big-o - Big O 或 Omega 符号中的变量 'C' 指的是什么