举例来说,斐波那契数列的迭代和递归版本。它们具有相同的时间复杂度吗?
答案很大程度上取决于您的实现。对于您给出的示例,有几种可能的解决方案,我想说,实现迭代的天真的方法具有更好的复杂性。这是两个实现:
int iterative_fib(int n) { if (n <= 2) { return 1; } int a = 1, b = 1, c; for (int i = 0; i < n - 2; ++i) { c = a + b; b = a; a = c; } return a; } int recursive_fib(int n) { if (n <= 2) { return 1; } return recursive_fib(n - 1) + recursive_fib(n-2); }
在这两种实现方式中,我都假定输入正确,即n> =1。第一种实现的代码更长,但是复杂度为O(n),即线性;而第二种实现的代码更短,但是具有指数复杂度O(fib(n))= O (φ^ n)(φ = (1+√5)/2),因此速度要慢得多。可以通过引入备注来改善递归版本(即,记住已经计算出的函数的返回值)。这通常是通过引入一个用于存储值的数组来完成的。这是一个例子:
φ = (1+√5)/2
int mem[1000]; // initialize this array with some invalid value. Usually 0 or -1 // as memset can be used for that: memset(mem, -1, sizeof(mem)); int mem_fib(int n) { if (n <= 2) { return mem[n] = 1; } if (mem[n-1] == -1) { solve(n-1); } if (mem[n-2] == -1) { solve(n-2); } return mem[n] = mem[n-1] + mem[n-2]; }
在这里,递归算法的复杂度是线性的,就像迭代解决方案一样。我上面介绍的解决方案是自上而下的动态编程解决方案。自下而上的方法将导致与我介绍的迭代解决方案非常相似的事情。关于动态编程的文章很多,包括维基百科
根据我所遇到的问题,有些问题很难通过自下而上的方法来解决(即迭代解决方案),而有些问题则很难用自上而下的方法来解决。但是,该理论指出,具有迭代解的每个问题都具有具有相同计算复杂度的递归(反之亦然)。
希望这个答案有帮助。