面试必刷算法TOP101之DP篇 TOP1

斐波拉契数列

题目来源:LeetCode

1、题目表述
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:

F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1

示例:

在这里插入图片描述
2、思路解析:

  • 1、 思路一:递归
    递归是比较常见的解题方式,其思路就是先利用性质求出转移方程式:fn=f(n-1)+f(n-2),将求解fn分解为求f(n-1)和f(n-2),利用递归的优点在进行子问题拆分,待递归达到停止条件n==1||n ==2开始回溯,反向求解。
    当在求第三项时,还得求出第一项和第二项,求N时后边的前N-1项还得重复求出,时间复杂度时2^n.
    当n很大时,会产生大量的重复元素,继而会产生大量的重复的方法调用,而每一次方法的调用,虚拟机都会在内存栈中重新分配空间以保存参数、返回地址和临时变量,而每个栈的容量是有限的,当递归调用层级太多时,会产生栈溢出,所以对于测试n=10,100,500,1000时,普通循环的时间消耗要明显小于递归实现。对于n很大时应该采用普通循环来计算斐波那契数列的值。
    但是递归的优点就是理解起来比较简单但是对于N越大其效率是成指数式增长,所以对于N比较大时递归方式就不再适用了。

  • 2、 思路二:dp
    分析前边的递归解题方法其解题过程中有着大量的重复计算,所以其效率随着N的增加就增加更快。
    在这里插入图片描述

3、代码实现

递归版:

int fib(int n) {
    if(n==1||n==2){
        return 1;
    }
    return fib(n-1)+fib(n-2);
    }

递归的停止条件就是当n1||n2就直接返回,然后开始回溯,反向求解。对于递归方式N很小时还可以运算,但是当N超过一定的数据范围,调度的时间就很长了。

时间复杂度为指数级别
dp版;

 class Fibonacci {
public:
    int getNthNumber(int n) {
   vector<int> num(n+1,0);
     for(int i=2;i<=n;i++){
         num[i]=num[i-1]+num[i-2];
     }
      return num[n];
    }
};

时间复杂度为O(N),空间复杂度为O(N);
但是这个代码额外的开辟了空间,所以可以在改进一下

class Fibonacci {
public:
    int getNthNumber(int n) {
   
    if(n==0||n==1){
        return 1;
    }
        long long fb;
        long long f0=1;
        long long f1=1;
     for(int i=2;i<=n;i++){
         fb=f1+f0;
         f0=f1;
         f1=fb;
     }
      return fb;
    }
};

既然要求第n项的斐波拉契数列所以就不用保存前n-1的数值,将每次求得第i项的数值保存在fb中然后更新f1和f2
空间复杂度为O(1),时间复杂度为O(N)。

疯狂青蛙跳台阶

题目来源:Leetcode

1、问题描述:
一只青蛙一次可以跳上1级台阶,也可以跳上2级…N级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。

示例:
在这里插入图片描述
2、思路解析

在这里插入图片描述
在这里插入图片描述
3、代码实现

int numWays(int n) {
        if(n==0){
            return 1;
        }
        int ret=1;
        for(int i=2;i<=n;i++){
            ret*=2;
        }
        return ret;
    }
        if(n==0){
            return 1;
        }
        return 1《《(n-1);
    }

根据转移方程式写代码就比较简单了,但是分析过程比较复杂。

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自首的小偷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值