这个简单程序的运行时间 - 时间复杂性

时间:2016-04-18 16:44:12

标签: java algorithm time time-complexity big-o

我想弄清楚这个简单程序的时间复杂程度是什么,但我似乎无法理解这是最好的方法。

我已经为每一行并列了时间复杂度

1    public int fnA (int n) {                   
2      int sum = 0;                    O(1)
3      for (int i = 0; i < n; i++) {   O(n)
4        int j = i;                    O(n)
5        int product = 1;              O(1)
6      
7        while (j > 1) {               O(n)
8          product ∗= j;               O(log n) 
9          j = j / 2;                  O(log n)
10       }
11       sum += product;               O(1)
12     }
13     return sum;                     O(1)
14   }

我是否正确假设这些运行时间并且最终运行时间为:O(n)

如果没有,有人能够解释我的错误吗?

总体而言:

1 + n + n + 1 + n + logn + logn + 1 + 1
= 3n + 2logn + 4

Final: O(n)

4 个答案:

答案 0 :(得分:2)

该算法的时间复杂度为O(NlogN)

for循环执行N次(从0N)。

while循环执行logN次,因为您每次将数字除以一半。

由于您正在执行while内的for,您正在执行logNN次操作,从那里O(NlogN)。< / p>

您可以假设所有剩余的操作(赋值,乘法,除法,求和)O(1)

答案 1 :(得分:2)

上述程序的关键是while循环,它是定义因素,其余行的复杂性不会超过O(n),并假设算术运算将在O(1)时间内运行。

mainMixerNode

以上循环的运行时间为O(log(j)),j从1变为n,所以它的系列......

while (j > 1) {              
  product ∗= j;             
  j = j / 2;                         
}

有关上述证明,请参阅this

答案 2 :(得分:1)

对于每个我都没有,logn循环正在运行,因此对于n元素,总复杂度为nlogn

因为您知道以下循环需要登录。

while (j > 1) {              
        product ∗= j;             
       j = j / 2;                         
}

现在为每个i执行此特定循环。所以这将被执行n次。所以它变成了nlogn

答案 3 :(得分:0)

首先,您可以统计所有操作。例如:

1    public int fnA (int n) {                   
2      int sum = 0;                    1
3      for (int i = 0; i < n; i++) {   
4        int j = i;                    n
5        int product = 1;              n
6      
7        while (j > 1) {               
8          product ∗= j;               ?
9          j = j / 2;                  ?
10       }
11       sum += product;               n
12     }
13     return sum;                     1
14   }

现在我们可以进行计数:equition总计:2 + 3n + nlog(n)

在许多程序中,计数更复杂,通常有一个突出的高阶项,例如:2 + 3n + 2n 2 。在谈论性能时,我们非常关心当n很大时,因为当n很小时,总和很小。当n很大时,更高阶项将绘制其余部分,因此在本例中 2n 2 实际上是重要的术语。所以这就是波浪线近似的概念。

考虑到这一点,通常可以快速识别最常执行的代码部分,并使用其计数来表示总体时间复杂度。在OP给出的示例中,它看起来像这样:

for (int i = 0; i < n; i++) {
    for (int j = i; j > 1; j /= 2)
        product *= j;
}

给出Σlog 2 n。通常计数涉及离散数学,我学到的一个技巧就是用它替换积分并做caculus:∫log 2 n = nlog(n)