[剑指offer][JAVA]面试题第[10-1]题[斐波那契数列][动态规划][记忆化递归]

239 篇文章 1 订阅
【问题描述】[中等]
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下:

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

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


【解答思路】
1. 动态规划

在这里插入图片描述
在这里插入图片描述
时间复杂度:O(N) 空间复杂度:O(1)

class Solution {
    public int fib(int n) {
        if(n == 0) return 0;
        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = 1;
        for(int i = 2; i <= n; i++){
            dp[i] = dp[i-1] + dp[i-2];
            dp[i] %= 1000000007;
        }
        return dp[n];
    }
}
2. 动态规划空间复杂度优化

dp[n + 1] -> abc
在这里插入图片描述
时间复杂度:O(N) 空间复杂度:O(1)

public int fib(int n) {
       if(n==0 ){
           return 0;
       }
       if(n==1 ){
           return 1;
       }
        int a = 0;
        int b = 1;
        int c = 0;
        for(int i =2; i<=n;i++){
            c =(a +b)%1000000007;
            a = b ;
            b = c ;
        }
         
          return  c;
    }
3. 递归(超时)

在这里插入图片描述
时间复杂度:O(2^N) 空间复杂度:O(1)

  public int fib(int n) {
      
        if(n==0) return 0;
        if(n==1) return 1;
        return (fib(n-1)+fib(n-2))%1000000007;
    }
4. 记忆化递归在这里插入图片描述

在这里插入图片描述
时间复杂度:O(N) 空间复杂度:O(1)

class Solution {
    public int fib(int n) {
        if(n == 0) return 0;
        int[] memorization = new int[n+1]; //用于存储第0~n个数对应的值
		memorization[1] = 1; //第一二个数先定义好,由于第一个数是0,默认即可不用写出
		return Fibonacci(n,memorization);
    }
    public int Fibonacci(int n,int[] memo) {
		if(n < 2 ) //当n等于0或1时,将不再往下递归,直接返回记忆化结果对应的值
			return memo[n];
		if(memo[n] > 0) //当遇到之前计算过的数时,将不再递归往下找,直接用记忆化结果
			return memo[n];
		memo[n] = (Fibonacci(n - 2, memo) + Fibonacci(n - 1, memo)) % 1000000007;
		return memo[n];
    }
}
【总结】
1.取余原因

“int32类型是十位数,对1e9取模可防止int32溢出”、“1e9+7是质数,对质数取模可以尽可能地让模数避免相等”以及“1e9+7是离1e9最近的质数,比较好记”

2.动态规划和记忆化递归区别

原理类似,动态规划有可能把空间复杂度降至 O(1)

3. 一开始就想到了方法二,其实方法二来源于动态规划的优化

转载链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/solution/mian-shi-ti-10-i-fei-bo-na-qi-shu-lie-dong-tai-gui/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值