小编典典

算法的迭代版本和递归版本是否具有相同的时间复杂度?

algorithm

举例来说,斐波那契数列的迭代和递归版本。它们具有相同的时间复杂度吗?


阅读 446

收藏
2020-07-28

共1个答案

小编典典

答案很大程度上取决于您的实现。对于您给出的示例,有几种可能的解决方案,我想说,实现迭代的天真的方法具有更好的复杂性。这是两个实现:

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),因此速度要慢得多。可以通过引入备注来改善递归版本(即,记住已经计算出的函数的返回值)。这通常是通过引入一个用于存储值的数组来完成的。这是一个例子:

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];
}

在这里,递归算法的复杂度是线性的,就像迭代解决方案一样。我上面介绍的解决方案是自上而下的动态编程解决方案。自下而上的方法将导致与我介绍的迭代解决方案非常相似的事情。关于动态编程的文章很多,包括维基百科

根据我所遇到的问题,有些问题很难通过自下而上的方法来解决(即迭代解决方案),而有些问题则很难用自上而下的方法来解决。但是,该理论指出,具有迭代解的每个问题都具有具有相同计算复杂度的递归(反之亦然)。

希望这个答案有帮助。

2020-07-28