剑指offer系列-----item7 斐波那契数列

61 篇文章 0 订阅
50 篇文章 0 订阅

题干:
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39

思路:
其实,斐波那契数列算是动态规划算法的究极简单例子之一了。目前的动态规划算法中的起始例子大多都是从斐波那契数列讲起。我这里就多啰嗦几句,说一下斐波那契数列。

F(n)= F(n-1)+ F(n-2),且F(1)=F(2)=1;

这就是斐波那契数列的通项式子。只不过这道题n是从0开始的而已。斐波那契数列之所以经常被放在动态规划当中讲是因为斐波那契数列的每一项都可以看做是某一个特定的状态,而这个状态是由过去的状态(n-1、n-2)来决定的。同时值得一提的是,这个状态还会影响未来的状态。也就是将一个大的问题分解成了若干个小问题的和的形式,这种问题一般是由动态规划来解决的。

使用动态规划求解问题,最重要的就是确定动态规划三要素:

(1)问题的阶段 (2)每个阶段的状态

(3)从前一个阶段转化到后一个阶段之间的递推关系。

递推关系必须是从次小的问题开始到较大的问题之间的转化,从这个角度来说,动态规划往往可以用递归程序来实现,不过因为递推可以充分利用前面保存的子问题的解来减少重复计算,所以对于大规模问题来说,有递归不可比拟的优势,这也是动态规划算法的核心之处。

确定了动态规划的这三要素,整个求解过程就可以用一个最优决策表来描述,最优决策表是一个二维表,其中行表示决策的阶段,列表示问题状态,表格需要填写的数据一般对应此问题在某个阶段某个状态下的最优值(如最短路径,最长公共子序列,最大价值等),填表的过程就是根据递推关系,从1行1列开始,以行或者列优先的顺序,依次填写表格,最后根据整个表格的数据通过简单的取舍或者运算求得问题的最优解。
递推公式或者叫做动态规划状态转移公式:
f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}

说了这么多,其实就是要告诉大家这道题,有两种解法:
1、传统递归
2、利用动态规划完成

具体代码见下:

//递归实现
public static int Fibonacci1(int n) {
        if(n==0 || n==1){
            return 1;
        }
        return Fibonacci1(n-1)+Fibonacci1(n-2);
    }
//动态规划实现
public static int Fibonacci(int n) {
        if(n==0 || n==1){
            return 1;
        }
        int dp[] = new int[n+1];//主要初始化数组的长度
        dp[0]=1;//初始化动态规划数组
        dp[1]=1;//初始化动态规划数组
        for(int i=2;i<n+1;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];
    }

我们来看一下采用递归方法和动态规划方法的时间长短:

5
采用递归耗时1.0毫秒
5
采用动态规划耗时0.0毫秒

明显采用递归耗时更多,因为递归有很多重复计算,而动态规划直接采用动态规划数组承载了过去的状态,即动态规划是在用空间换时间的一种算法,在内存空间较为宽裕而对运行时间要求比较高的场景中应用广泛。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值