简体   繁体   English

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

[英]Calculate the time complexity of this specific algorithm

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(); 
 }

From: problem 来自: 问题

MY CALCULATION: 我的计算:

The first loop has (str.length - 1) rotations. 第一个循环旋转(str.length-1)。 The second loop depends on the first loop, so it goes like: (0), [0, 1], [0, 1, 2] , ... , [0, 1 .., str.length - 2] Thus this is a total of (Second loop only) 1 + 2 + ... + N - 2 = (2N-3)^2/8 -1/8 ~ (2N)^2. 第二个循环依赖于第一个循环,因此它类似于:(0),[0、1],[0、1、2],...,[0、1 ..,str.length-2]因此这是总计(仅第二个循环)1 + 2 + ... + N-2 =(2N-3)^ 2/8 -1/8〜(2N)^ 2。 If we let N=str.length. 如果我们让N = str.length。 In the first loop, we have (N-1) ~ N, thus a total of ~N^3. 在第一个循环中,我们有(N-1)〜N,因此总计〜N ^ 3。 But then we have to assume that inside both the loops, it is O(1) otherwise we have have > O(N^3)? 但是,我们必须假设在两个循环中,它都是O(1),否则我们有> O(N ^ 3)?

But I don't think this is right. 但是我认为这是不对的。

How do we calculate such a time complexity? 我们如何计算这样的时间复杂度?

If n is the length of str . 如果nstr的长度。

The external loop can be approximated (as you did) to O(n) . 外部循环可以像您所做的那样近似为O(n)

The inner loop can be approximated to O(n) too, because it goes from a minimum of 0 cycles to a maximum of n cyles when length is 0. 内部循环也可以近似为O(n) ,因为当length为0时,它从最小的0个循环到最大的n个循环。

So if you DON'T consider what happens internally in substring and replaceAll methods the complexity is O(n) * O(n) -> O(n^2). 因此,如果您不考虑substringreplaceAll方法内部发生的情况,复杂度为 O(n)* O(n)-> O(n ^ 2)。


Note that the replaceAll iterate over the whole string, so his internal complexity is O(n). 注意replaceAll遍历整个字符串,因此他的内部复杂度为O(n)。 Considering also this the complexity is O(n^3). 还考虑到这一点,复杂度为O(n ^ 3)。

Assuming n is length of str , you get: 假设nstr长度,则得到:

  • Outer loop iterates n - 1 times: O(n) 外循环迭代n - 1次: O(n)
  • Inner loop iterates 1 to n - 1 times, so on average n / 2 times: O(n) 内循环迭代1到n - 1次,因此平均重复n / 2次: O(n)
  • replaceAll() inside countVowels() iterates over 2 to n characters, so on average n / 2 + 1 times: O(n) countVowels() replaceAll()内的countVowels()迭代2到n字符,因此平均n / 2 + 1次: O(n)
  • Total is O(n) * O(n) * O(n) , so: O(n 3 ) 总计为O(n) * O(n) * O(n) ,因此: O(n 3

Note: Performance of substring() depends on version of Java , so it is either O(1) (earlier Java) or O(n) (later Java). 注意: substring()性能取决于Java的版本 ,因此它是O(1) (Java的早期版本)或O(n) (Java的后期版本)。 But since O(1) + O(n) and O(n) + O(n) is both O(n) , it makes no difference for performance of inner loop body, which is why the above logic only considers the performance of replaceAll() . 但是由于O(1) + O(n)O(n) + O(n)都是O(n) ,所以它对内部循环体的性能没有影响,因此上述逻辑只考虑了replaceAll()


UPDATE UPDATE

There are three ways of calculating performance for outer and inner loop combined, excluding what happens in the body: 有三种方法可以计算外环和内环组合的性能,但不包括主体中发生的情况:

  1. O math: Outer loop is O(n) , and inner loop is O(n) , so total is O(n) * O(n) = O(n 2 ) O数学:外循环为O(n) ,内循环为O(n) ,所以总计为O(n) * O(n) = O(n 2

  2. Iteration math: Outer loop iterates n - 1 times, and inner loop iterates n / 2 times (on average) , so total is (n - 1) * (n / 2) = n² / 2 - n / 2 . 迭代数学:外循环迭代n - 1次,内循环迭代n / 2(平均) ,因此总计为(n - 1) * (n / 2) = n² / 2 - n / 2 Since only fastest growing factor counts, that means O(n 2 ) 由于只有增长最快的因子才算,这意味着O(n 2

  3. Iteration sum: Sum the iterations of inner loop, ie 1 + 2 + ... + n-1 . 迭代总和:求和内循环的迭代,即1 + 2 + ... + n-1 Sum of a sequence can be calculated as count * average , and average can be calculated as (min + max) / 2 . 序列的总和可以计算为count * average ,平均可以计算为(min + max) / 2 That means that average = (1 + n-1) / 2 = n / 2 , and sum = (n - 1) * (n / 2) , which is exactly the same result we got in #2 above, so it is O(n 2 ) 这意味着average = (1 + n-1) / 2 = n / 2sum = (n - 1) * (n / 2) ,这与我们在上面的#2中得到的结果完全相同,因此O(n 2

As you can see, O math was simpler, so that's why it was chosen for the answer. 如您所见, O数学更简单,因此才选择答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM