这个特定函数的时间复杂度\ big(O)是多少?

时间:2018-10-05 22:47:15

标签: c loops time-complexity big-o complexity-theory

此函数(f1)的时间复杂度是多少?

我可以看到第一个循环(i = 0)->(n / 4次)第二个循环(i = 3)->(n / 4-3次)...等等,结果是:(n / 3)*(n / 4 +(n-3)/ 4 +(n-6)/ 4 +(n-9)/ 4 ....

我在这里停下来,如何继续?

int f1(int n){
  int s=0;
  for(int i=0; i<n; i+=3)
    for (int j=n; j>i; j-=4)
      s+=j+i;
  return s;
}

3 个答案:

答案 0 :(得分:3)

Big(O)表示法的重要之处在于它消除了“常量”。目的是随着输入量的增长确定趋势,而不必担心特定数字。

将其视为在不知道x轴和y轴的数字范围的图形上确定曲线。

因此,在您的代码中,即使您为每个循环的每次迭代都跳过n范围内的大多数值,这也是以恒定的速率完成的。因此,无论您实际上跳过了多少,这仍然相对于n^2进行缩放。

计算以下任何内容都没关系:

1/4 * n^2
0.0000001 * n^2
(1/4 * n)^2
(0.0000001 * n)^2
1000000 + n^2
n^2 + 10000000 * n

在Big O中,这些都等效于O(n^2)。关键是一旦n变得足够大(无论可能是多少),所有低阶项和常数因子在“全局”中都将变得无关紧要。

值得强调的是,这就是为什么在小投入时您应该警惕过分依赖Big O的原因。那时候恒定的间接费用仍然会产生很大的影响。

答案 1 :(得分:1)

关键观察:内部循环在步骤(n-i)/4中执行i次,因此在步骤i/4中执行n-i

现在将i = 3k, 3(k-1), 3(k-2), ..., 9, 6, 3, 0的所有这些数量相加,其中3k3之前n(即3k <= n < 3(k+1))的最大倍数:

3k/4 + 3(k-1)/4 + ... + 6/4 + 3/4 + 0/4 = 3/4(k + (k-1) + ... + 2 + 1)
                                        = 3/4(k(k+1))/2
                                        = O(k^2)
                                        = O(n^2)

因为k <= n/3 <= k+1,因此还有k^2 <= n^2/9 <= (k+1)^2 <= 4k^2

答案 2 :(得分:-1)

理论上是“ O(n * n)”,但是...

如果编译器想对其进行优化,该怎么办?

String.join(DELIMITER,
    SET1.contains(event) ? VALUE1 : SKIP,
    SET2.contains(event) ? VALUE2 : SKIP,
    SET3.contains(event) ? VALUE3 : SKIP,
    SET4.contains(event) ? VALUE4 : SKIP
);

甚至是这样:

int f1(int n){
  int s=0;
  for(int i=0; i<n; i+=3)
    s += table[i];
  return s;
}

然后它也可以是“ O(n)”或“ O(1)”。

请注意,从表面上看,这种优化似乎是不切实际的(由于最坏情况下的内存成本);但是使用足够先进的编译器(例如,使用“整个程序优化”来检查所有调用者,并确定int f1(int n){ if(n <= 0) return 0; return table[n]; } 始终在某个范围内),这是不可想象的。以类似的方式,并非所有调用方都使用常量(例如,使用足够先进的编译器可以将n之类的内容替换为x = f1(123);)。

换句话说;实际上,原始函数的时间复杂度取决于该函数的使用方式以及编译器的优劣。