算法笔记:递归&迭代

例题1 阶乘函数

int func(int n){
  if(n<0) return -1;
  if(n==0) return 1;
  return n*func(n-1);  
}

一个完整的阶乘函数应该像上面一样写,一般的书都是默认了输入的时候不会输出超过范围的数字,但是我们自己写程序的时候,应该要考虑所有的情况。一个递归应该能让所有输入的值都有一个出口。

所以一般来说,递归应该由三个部分组成:递归体(自己调用自己),递归出口,和容错。

 

例题2 斐波那契数列

int func(int n){
  if(n<0) return -1;
  if(n==1) return 1;
  return func(n-1)+func(n-2);  
}

这两个例题,都是最基本的递归入门函数。但假如,我们要使用不支持递归的语言去实现递归的作用,那我们应该?

对于任何递归函数,都存在功能等价的迭代实现

 

所以让我们试着,把上面两个任务,都用迭代的方法去实现:

阶乘函数:

int func(int n){
   int p=1;
   for(int i=2;p<=n;i++){
       p=p*(i-1)
   }
   return p;
}

斐波那契数列:

int func(int n){
  int a=1,b=1,c=1;
  for(int i=2;i<=n;i++){
      c = a+b;
      b = c;
      a = b; 
  }
  return c;
}

那么此时,问题来了?我们不可能同时写两种方法,我们应该如何选择更好的写法?

对于例题一来说,递归函数,要计算n次,时间复杂度是O(n),空间复杂度也是O(n)。迭代的方法呢,计算n次,时间复杂度是O(n),空间复杂度是O(1),自己新用到了一个变量,所以两个的差别并不大,都可以选择。

对于例题二来说,递归函数,我们可以画一个类似于二叉树的模型,根据规律大概可以估算它每次给n加1,计算就要翻倍,实际是要计算大概1.618的n次方次,所以时间复杂度大概是O(2^n)次,而空间复杂度也差不多是这样,根据实际的测算,计算n=100的时候,就等到咱去世了也没有结果0_0,可以说是一个并没什么用的程序了。而对迭代函数来说,还是计算n次,空间复杂度也是n(1),所以这时候,迭代的效率要高很多。

所以我们对比也得到了递归函数的优点和缺点,优点是易理解方便,缺点是性能差,原因有两个:1.必须递归栈的支持;2.可能出现子问题重叠现象。

 

posted @ 2017-09-19 14:45  章鱼小年糕  阅读(205)  评论(0编辑  收藏  举报