这个c函数的复杂性是什么?

时间:2010-12-25 06:43:36

标签: c algorithm complexity-theory

以下c函数的复杂性是什么?

double foo (int n) {
    int i;
    double sum;
    if (n==0) return 1.0;
    else {
        sum = 0.0;
        for (i =0; i<n; i++)
        sum +=foo(i);
        return sum;
    }
}

请不要发布复杂性,你可以帮助我理解如何去做。

编辑:这是考试中提出的客观问题,提供的选项是  1.O(1)  2.O(n)的  3.O(N!)  4.O(n ^ n)

4 个答案:

答案 0 :(得分:10)

它是Θ(2 ^ n)(假设f是我们算法的运行时间):

f(n) = f(n-1) + f(n-2) + ... + 1
f(n-1) = f(n-2) + f(n-3) + ...
==> f(n) = 2*f(n-1), f(0) = 1
==> f(n) is in O(2^n)

实际上,如果我们忽略常数操作,那么确切的运行时间是2 n

同样在你写的这是一个考试的情况下,O(n!)和O(n ^ n)都是真的,并且它们中最接近Θ(2 ^ n)的答案是O(n!),但是如果我是学生,我会标记他们两个:)


关于O(n!)的解释:

for all n >= 1: n! = n(n-1)...*2*1 >= 2*2*2*...*2 = 2^(n-1) ==>
2 * n! >= 2^n ==> 2^n is in O(n!),
Also n! <= n^n for all n >= 1 so n! is in O(n^n)

So O(n!) in your question is nearest acceptable bound to Theta(2^n)

答案 1 :(得分:2)

首先,它的编码很差:)

double foo (int n) {         // foo return a double, and takes an integer parameter
    int i;                   // declare an integer variable i, that is used as a counter below
    double sum;              // this is the value that is returned
    if (n==0) return 1.0;    // if someone called foo(0), this function returns 1.0
    else { // if n != 0
        sum = 0.0;           // set sum to 0
        for (i =0; i<n; i++) // recursively call this function n times, then add it to the result
        sum +=foo(i);
        return sum;          // return the result
    }
}

你正在调用foo()总共类似n ^ n(你将n舍入到最接近的整数)

e.g:

foo(3)将被称为3 ^ 3次。

祝你好运,祝圣诞快乐。

编辑:哎呀,刚刚纠正了一些事情。为什么foo会返回双倍?它总是返回一个整数,而不是一个整数。

这将是一个更好的版本,微优化! :d

int foo(int n)
{
    if(n==0) return 1;
    else{
        int sum = 0;
        for(int i = 0; i < n; ++i)
        sum += foo(i);
        return sum;
    }
}

答案 2 :(得分:1)

你可能会更清楚...... 发牢骚

<n = ?> : <return value> : <number of times called>
n = 0 : 1 : 1
n = 1 : 1 : 2
n = 2 : 2 : 4
n = 3 : 4 : 8
n = 4 : 8 : 16
n = 5 : 16 : 32
n = 6 : 32 : 64
n = 7 : 64 : 128
n = 8 : 128 : 256
n = 9 : 256 : 512
n = 10 : 512 : 1024

number_of_times_called = pow(2,n-1);

让我们尝试输入输入,是吗?

使用此代码:

#include <iostream>

double foo (int n) {
    int i;
    double sum;
    if (n==0) return 1.0;
    else {
        sum = 0.0;
        for (i =0; i<n; i++)
        sum +=foo(i);
        return sum;
    }
}


int main(int argc, char* argv[])
{
    for(int n = 0; 1; n++)
    {
       std::cout << "n = " << n << " : " << foo(n);
       std::cin.ignore();
 }

    return(0);
}

我们得到:

n = 0 : 1
n = 1 : 1
n = 2 : 2
n = 3 : 4
n = 4 : 8
n = 5 : 16
n = 6 : 32
n = 7 : 64
n = 8 : 128
n = 9 : 256
n = 10 : 512

因此,它可以简化为:

double foo(int n)
{
    return((double)pow(2, n));
}

答案 3 :(得分:0)

该功能由多个部分组成。

复杂性的第一位是if(n==0)return 1.0;,因为它只生成一次运行。那将是O(1)

下一部分是for(i=0; i<n; i++)循环。由于该0..n的循环为O(n)

与递归相比,n中的每个数字都会再次运行该函数。并在该函数中再次循环,以及下一个函数。等等...

要弄清楚它会是什么我建议你在循环中添加一个全局计数器,这样你就可以看到它对某个数字执行了多少次。