有关递归和斐波那契数列

求斐波那契数列第N项,最简单的方法

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

但显然这很低效,因为会重复计算很多次前面的值,比如算f(10),要得到f(9),和f(8),而求f(9)要求f(8) 和f(7),求f(8)要求f(7)和f(6),就重复计算了f(8)和f(7),越往后重复的越多,总复杂度为指数级,效率极低
我们可以将前面的计算结果存起来,避免重复计算

int f(int n)
{
   int* arr = new int[n];
   arr[0] = 1;
   arr[1] = 1;
   for(int i = 2;i < n;i++)
   {   
      arr[i] = arr[i - 1] + arr[i - 2];
   }
   return arr[n - 1];
}

这样效率虽高,但占用额外的空间,仔细想想,每次结果只与前两次结果有关,可以优化优化

int f(int n)
{
   if(n <= 2) return 1;
   int first = 1;
   int second = 1;
   int ans;
   for(int i = 3;i <= n;i++)
   { 
      ans = first + second;
      first = second;
      second = ans;
   }
   return ans;
}

这被称为迭代,无论是在时间上还是在空间上都很高效。
运用上述思想,来看下经典的爬楼梯问题

题目描述
假设你正在爬楼梯。需要 n 阶你才能到达楼顶
每次你可以爬 12 个台阶。你有多少种不同的方法可以爬到楼顶呢?

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1+ 12.  2 阶

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
4.  1+ 1+ 15.  1+ 26.  2+ 1

法一

//方法一,记忆化递归
   int ans(int i,int n,int arr[])
    {
        if(i > n)
            return 0;
        if(i == n)
            return 1;
        if(arr[i] > 0)
            return arr[i];
        arr[i] = ans(i + 1,n,arr) + ans(i + 2,n,arr);
        return arr[i];
    }
     int climbStairs(int n) 
    {
        int* arr = new int[n];
        for(int i = 0;i < n;i++)
        {
            arr[i] = 0;
        }
        return ans(0,n,arr); 
    }

法二

int climbStairs(int n) {
 int* arr = new int[n];
        if(n == 1)
            return 1;
        arr[0] = 1;
        arr[1] = 2;
        for(int i = 2;i < n;i++)
            arr[i] = arr[i -1] + arr[i - 2];
        return arr[n - 1];
  }

法三

 int climbStairs(int n) {
     if(n <= 2)
          return n;
        int first = 1;
        int second = 2;
        int third;
        for(int i = 3;i <= n;i++)
        {
            third = first + second;
            first = second;
            second = third;
        }
        return third;
     }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值