计算此特定算法的时间复杂度

时间:2016-09-21 15:30:44

标签: java algorithm time-complexity

public static String findLongestSubstring(String str) {
for (int len = str.length(); len >= 2; len--) {
    for (int i = 0; i <= str.length() - len; i++) {
        String substr = str.substring(i, i + len);
        int vowels = countVowels(substr);
        int consonants = len - vowels;
        if (vowels == consonants) {
            return substr;
        }
    }
}
return "";
}

private static int countVowels(String str) {
return str.replaceAll("[^AEIOUaeiou]+", "").length(); 
 }

自:problem

我的计算:

第一个循环有(str.length - 1)个旋转。第二个循环取决于第一个循环,所以它类似于:(0),[0,1],[0,1,2],...,[0,1 ...,str.length - 2]因此这是总共(仅第二循环)1 + 2 + ... + N - 2 =(2N-3)^ 2/8 -1 / 8~(2N)^ 2。如果我们让N = str.length。在第一个循环中,我们有(N-1)~N,因此总共~N ^ 3。但是我们必须假设在两个循环中,它是O(1)否则我们有&gt; O(N ^ 3)?

但我不认为这是对的。

我们如何计算这样的时间复杂度?

2 个答案:

答案 0 :(得分:2)

如果nstr的长度。

外部循环可以近似(正如您所做) O(n)

内环也可以近似为 O(n),因为{{1}时它从最少的0个循环变为最大的n个循环}是0。

因此,如果您不考虑lengthsubstring 方法内部发生的情况,复杂性 O(n)* O( n) - &gt;的为O(n ^ 2)。

请注意replaceAll遍历整个字符串,因此其内部复杂度为O(n)。考虑到这一点,复杂性是O(n ^ 3)。

答案 1 :(得分:2)

假设n的长度为str,您会得到:

  • 外循环迭代n - 1次: O(n)
  • 内部循环迭代1到n - 1次,因此平均n / 2次: O(n)
  • {li> replaceAll()countVowels()内迭代2到n个字符,因此平均n / 2 + 1次: O(n)
  • 总计 O(n) * O(n) * O(n),因此: O (N 3

注意: substring()的效果取决于version of Java,因此它是 O(1)(早期Java)或 O(n)(后来的Java)。但是因为 O(1) + O(n) O(n) + O(n)是两个 O(n),它对内部循环体的性能没有影响,这就是为什么上述逻辑只考虑replaceAll()的性能。

<强>更新

计算外循环和内循环的性能有三种方法,不包括正文中的内容:

  1. O 数学:外环是 O(n),内环是 O(n),所以总数是 O(n) * O(n) = O(n 2

  2. 迭代数学:外循环迭代n - 1次,内循环迭代n / 2(平均),因此总计为(n - 1) * (n / 2) = n² / 2 - n / 2。由于只有增长最快的因子计数,这意味着 O(n 2

  3. 迭代和:对内循环的迭代求和,即1 + 2 + ... + n-1。序列的总和可以计算为count * average,平均值可以计算为(min + max) / 2。这意味着average = (1 + n-1) / 2 = n / 2sum = (n - 1) * (n / 2),这与我们在上面#2中获得的结果完全相同,因此它是 O(n 2

  4. 正如您所看到的, O 数学更简单,因此这就是为什么选择答案的原因。