找出函数“foo”的时间复杂度

时间:2016-02-10 21:50:48

标签: c algorithm time-complexity

我很难找到此功能的时间复杂度

void foo(int n) {
    int i, m = 1;
    for (i = 0; i < n; i++) {
        m *= n; // (m = n^n) ??
    }
    while (m > 1) {
        m /= 3;
    }
}

嗯,迭代的第一个显然是O(n^n),对它的解释是因为m started with value 1,并且自己加倍n次。

现在,我们使用m = n^n启动while循环,然后每次将其除以3。 这意味着,(我猜),log(n^n)

假设我到现在为止,我不确定我是否需要求和或乘,但我的逻辑说我需要求和它们,因为它们对每个都是“奇怪的”其他

所以我的假设是:O(n^n) + O(log(n^n)) = O(n^n)因为如果n非常大,我们可以避免O(log(n^n))

嗯,我在这里做了很多假设,我希望这是有道理的。我很想听听你对这个功能的时间复杂性的看法。

2 个答案:

答案 0 :(得分:2)

理论上,时间复杂度为O(n log n),因为:

for (i=0; i<n; i++) 
   m *= n;

这将执行n次,最后m=n^n

然后这个

while (m>1)
   m /= 3;

将执行log3(n^n)n * log3(n)

P.S。但这只有在您计算操作次数时才会这样。在现实生活中,计算n^n需要花费更多的时间,因为数字变得太大了。此外,当你将这些大数字相乘时,你的函数会溢出,而且很可能你会受到int的最大数量的限制(在这种情况下,复杂性将是O(n)

答案 1 :(得分:0)

使用foo(int n)和32位intn不能超过10,否则m *= n会溢出。

鉴于n工作的范围很小,O()似乎没有实际意义。即使使用64位无符号mn <= 15

也是如此

所以我认为O(n lg(n))在技术上是正确的,但考虑到int的约束,可疑代码花费更多时间来执行单printf()而不是遍历foo(10) }。 IOWs它实际上 O(1)。

unsigned long long foo(int n) {
  unsigned long long cnt = 0;
  int i;
  unsigned long long m = 1;
  for (i = 0; i < n; i++) {
    if (m >= ULLONG_MAX/n) exit(1);
    m *= n; // (m = n^n) ??
    cnt++;
  }
  while (m > 1) {
    m /= 3;
    cnt++;
  }
  return cnt;
}

并想出了

1 1
2 3
3 6
4 9
5 12
6 16
7 19
8 23
9 27
10 31
11 35
12 39
13 43
14 47
15 52