NC65:斐波那契数列/LeetCode:509.斐波那契数

斐波那契数列

https://www.nowcoder.com/practice/c6c7742f5ba7442aada113136ddea0c3?tpId=188&&tqId=38580&rp=1&ru=/activity/oj&qru=/ta/job-code-high-week/question-ranking

1、介绍

斐波那契数列(Fibonacci sequence),又称黄金分割数列或兔子数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……
标准公式为:
简单理解就是从第二项开始,当前值等于前两项之和

2、解法

(1)递归法

分析

根据标准公式为:采用递归进行细化拆分
先从上往下递归,然后再从下往上回溯,最后回溯的时候合并子树求得答案。

代码实现

public class Solution {
    public int Fibonacci(int n) {
        if(n == 0 || n == 1){
            return n;
        }
        return Fibonacci(n-1) + Fibonacci(n-2);
    }
}
优点:代码简单好写,缺点:慢,会超时
时间复杂度:

空间复杂度:

(2)动态规划(优化递归)

分析

  • 通过上图会发现,方法一中使用递归会存在很多重复计算,因此为了改进,可以把使用数组将计算过的保存下来。
  • 如果想让空间继续优化,那就用动态规划,优化掉递归栈空间,方法一是从上往下递归的然后再从下往上回溯的,在最后的回溯过程中来合并子树从而求得答案。
  • 而使用动态规划,不用递归的过程,直接从子树求得答案,过程是从下往上。

代码实现1

public class Solution {
    public int Fibonacci(int n) {
        int ans[] = new int[40];//因为此题n≤39,所以直接设置数组大小为40
        ans[0] = 0;
        ans[1] = 1;
        for(int i=2; i<=n; i++){//从第二项开始计算到第n项,用数组进行保存
            ans[i] = ans[i-1] + ans[i-2];
        }
        return ans[n];
    }
}

代码实现2

根据输入的n确定数组的大小,n小于等于1就直接确定数组的值,大于1就从第三项开始计算到第n项,用数组进行保存

class Solution {
    public int fib(int n) {
        int[] dp = new int[n+1];
        if(n == 0){
            dp[0] = 0;
        }else if(n == 1){
            dp[0] = 0;
            dp[1] = 1;
        }else{
            dp[0] = 0;
            dp[1] = 1;
            for(int i = 2; i <= n; i++){
                dp[i] = dp[i - 1] + dp[i - 2];
            }
        }
        return dp[n];
    }
}

时间复杂度:
空间复杂度:

(3)动态规划(优化存储)

分析

因为从第二项开始,当前值等于前两项之和,所以可以使用三个变量:
存储第n-2项的值,存储第n-1项的值,存储第n项的值,

代码实现

public class Solution {
    public int Fibonacci(int n) {
        if(n <= 0){
            return 0;
        }
        if( n == 1){
            return 1;
        }
        int n1 = 0;
        int n2 = 1;
        int n3 = 0;
        for(int i = 2; i <= n; i++){
            n3 = n1 + n2; //根据前两项计算当前值
            n1 = n2;//n1,n2继续表示下一项的值
            n2 = n3;
        }
        return n3;
    }
}

时间复杂度:
空间复杂度:

3、扩展

题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

分析

根据题意得,跳台阶n从0开始的规律为0,1,2,3,5,8,13......与斐波那契数列类似,只是少了一个1
n3 = n1 + n2;
n1 = n2;
n2 = n3;
//可使用两个参数实现优化
n2 = n1 + n2; //这里n2相当于获得了n3的值
n1 = n2 - n1; //n1获得了n2的值

实现代码

public class Solution {
    public int jumpFloor(int target) {
        if(target <= 0){
            return 0;
        }
        if( target < 4){ //数列为0,1,2,3,5,8,13...
            return target;
        }
        int n1 = 2;
        int n2 = 3;
        for(int i = 4; i <= target; i++){//这里需要从第四项开始
            n2 = n1 + n2;
            n1 = n2 - n1;
        }
        return n2;
    }
}

全部评论

相关推荐

我在朝九晚六双休的联想等你:如果我是你,身体素质好我会去参军,然后走士兵计划考研211只需要200多分。
点赞 评论 收藏
分享
10-30 10:16
南京大学 Java
永远的鹅孝子:给南大✌️跪了
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务