斐波那契递归不超时的写法(备忘录写法)

斐波那契数列不超时的写法(备忘录写法)

原理,在原先的写法中是直接return f(n-1)+f(n-2)然后一直形成递归的。

但是如果我们用一个数组,来把递归算出来的数存放进来,并且在递归的时候进行判断,

如果这个数组里面有这个数,就将他拿出来直接使用,节省了再一次递归所用的时间。

可能我说的不是很好理解看图:

首先假如n = 10 ,为了方便我不会画成f(10)=f(9)+f(8),而是直接 画成 10= 9+8

image-20220218170442511

可以很明显的看出,如果递归正常操作的话,画成树状图,会有无数的支点,绿色部分即是那无数的支点,不过我将他省略。

因为我们的目的就是算出红色部分的支点,将绿色部分给减掉。并将红色部分的支点存放起来。

因为递归是按顺序递归的,比如10=9+8。这个时候就会调用9 ,然后9= 8+7,以此类推下去,最后到了2=1+0;数据值用一个数组存放。得出数组[2]=数据值。然后我们就知道了f(10)-f(0) 的数据值,并将他们全部存放进数组。这样子一次递归的时候直接使用。

为什么说省时间呢?因为上面的那一次递归只是10=9+8.其中的9引起的递归。98765432。这些只是他的一个支点,他还有另一个支点。

而算完他那部分递归下去的所有支点,别忘了10=9+8;的8还没有递归。上面的8是9下面的支点。这个8是10下面的支点。所以我们要递归无数次才能得出最后的f(10)=多少(数据值)

package 数据结构.递归;

public class 斐波那契备忘录递归 {
    public static void main(String[] args) {
        Solution03 s = new Solution03();
        System.out.println(s.fib(10));
    }
}
class Solution03 {
    int fib(int N) {
        // 备忘录全初始化为 0
        int[] memo = new int[N + 1];
        // 进行带备忘录的递归
        return helper(memo, N);
    }
    int helper(int[] memo, int n) {
        // base case
        if (n == 0 || n == 1) return n;
        // 已经将已知的f(n)存放进去这个数组了。不了解可以看下上面的解析。我说的不好。比较推荐你们debug一下
        if (memo[n] != 0) return memo[n];
        memo[n] = helper(memo, n - 1) + helper(memo, n - 2);		//这个就是将数据值存放进数组。因为没有直接return数据值,而是将他存放进数组。这样我们只需要存放他需要递归的无数个节点的10个或者说n个。等需要用的时候直接代入即可。
        return memo[n];
    }
}

image-20220218171804057

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值