斐波那契数列相关问题总结

一. 原问题

在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1, F(n)=F(n-1)+F(n-2)(n>=2,n∈N*),即从第三项开始,每一项等于前两项之和。

输入格式:输入包括一行,包括一个整数N (0≤N≤50)。

输出格式:输出包括一行,包括一个整数,为斐波那契数列的第 N 项的值。

  1. 递归方法
    时间复杂度为O(2^n)。

    import java.util.Scanner;
    
    public class Fibonacci_1 {
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            int n = input.nextInt();
            long f = fib(n);
            System.out.println(f);
        }
    
        public static long fib(int n) {
            if(n == 0){
                return 0;
            }else if (n == 1){
                return 1;
            }else {
                return fib(n - 1) + fib(n - 2);
            }
        }
    }
  2. 数组存储,动态规划

    当一个问题可以分解成若干重复的子问题时,运用动态规划的思想:只需要将子问题求解一次,以后再遇到,直接调用,所以新建一个数组用于存储子问题的结果。(以空间换时间)

    import java.util.Scanner;
    
    public class Fibonacci_2 {
    
        static Scanner input = new Scanner(System.in);
        static int n = input.nextInt();
        static long[] result = new long[n + 1];
    
        public static void main(String[] args) {
            long f = fib(n);
            System.out.println(f);
        }
    
        public static long fib(int n) {
            long f = 0;
            if(n == 0){
                f = 0;
            }else if (n == 1){
                f = 1;
            }else if (result[n] > 0){
                return result[n];
            }else {
                f = fib(n - 1) + fib(n - 2);
            }
            result[n] = f;
            return f;
        }
    }
    
  3. 递推方法
    时间复杂度为O(n)

    import java.util.Scanner;
    
    public class Fibonacci_3 {
        public static void main(String[] args) {
            long f0 = 0;
            long f1 = 1;
            long f = 0;
            Scanner input = new Scanner(System.in);
            int n = input.nextInt();
    
            if(n == 0){
                f = 0;
            }else if(n == 1){
                f = 1;
            }else {
                for(int i = 2; i <= n; i++){
                    f = f0 + f1;
                    f0 = f1;
                    f1 = f;
                }
            }
    
            System.out.println(f);
        }
    }
  4. 矩阵相乘算法

    推导过程:
    Fibonacci_1
    Fibonacci_2
    由此演变成了求Fibonacci_3此矩阵的(n - 1)次方的过程。

    import java.util.Scanner;
    
    public class Fibonacci_4{
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            int n = input.nextInt();
            long f = fib(n);
            System.out.println(f);
        }
    
        public static long[][] baseMartrixMulti(int n) {
            long[][] result = {{1, 0}, {0, 1}};//单位阵
            long[][] base = {{1, 1}, {1, 0}};
            long[][] temp = {{1, 0}, {0, 1}};
            for (int i = 0; i < n; i++){
                result[0][0] = temp[0][0] * base[0][0] + temp[0][1] * base[1][0];
                result[0][1] = temp[0][0] * base[0][1] + temp[0][1] * base[1][1];
                result[1][0] = temp[1][0] * base[0][0] + temp[1][1] * base[1][0];
                result[1][1] = temp[1][0] * base[0][1] + temp[1][1] * base[1][1];
                temp[0][0] = result[0][0];//特别注意,数组赋值赋的是引用,不能直接temp = result;
                temp[0][1] = result[0][1];
                temp[1][0] = result[1][0];
                temp[1][1] = result[1][1];
            }
            return result;
        }
    
        public static long fib(int n) {
            long f = 0;
            if(n != 0){
                long[][] trans = baseMartrixMulti(n - 1);
                f = trans[0][0];//意义为下两条注释的语句
                //long[][] bas = {{1}, {0}};
                //f = trans[0][0] * bas[0][0] + trans[0][1] * bas[1][0];
            }
            return f;
        }
    }

    矩阵相乘和乘方可以单独抽象出来函数,此处只是为了解决固定矩阵的乘方问题,没有给出普适代码,若有需要参考 矩阵乘法求斐波那契数列

    此过程中发现乘方优化算法,参考 乘方的优化算法,可结合到矩阵乘方,待研究后贴出代码。

  5. 公式法

    Fibonacci_4

    万能的数学家得出斐波那契数列通项公式如上,推导过程略(其实是因为看不懂,有兴趣自行百度 orz)。又称为“比内公式”,是用无理数表示有理数的一个范例。

    代码实现如下:

    import java.util.Scanner;
    
    public class Fibonacci_5 {
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            int n = input.nextInt();
            long f = (long)((Math.pow((1 + Math.sqrt(5)) / 2, n) - Math.pow((1 - Math.sqrt(5)) / 2, n)) / Math.sqrt(5));
            System.out.println(f);
        }
    }

二. 引申问题

  1. 爬楼梯问题

    假设你现在正在爬楼梯,楼梯有 n 级。每次你只能爬 1 级或者 2 级,那么你有多少种方法爬到楼梯的顶部?

    输入格式:第一行输入一个整数 n(1≤n≤50),代表楼梯的级数。

    输出格式:输出爬到楼梯顶部的方法总数。

    其实相当于斐波那契问题,只是初始条件改变。f(1) = 1, f(2) = 2, n > 2时,f(n) = f(n - 1) + f(n - 2) 。 (若用矩阵运算可以将base矩阵减少一阶,也可以虚拟假设 f(0) = 1)

    任选一种以上方法给出代码:

    import java.util.Scanner;
    
    public class Climb {
        public static void main(String[] args) {
            long f0 = 1;
            long f1 = 1;
            long f = 0;
            Scanner input = new Scanner(System.in);
            int n = input.nextInt();
            if(n == 1){
                f = 1;
            }else{
                for(int i = 2; i <= n; i++){
                    f = f0 + f1;
                    f0 = f1;
                    f1 = f;
                }
            }
            System.out.println(f);
        }
    }
  2. 疯狂跳台阶
    (题目来源于http://blog.youkuaiyun.com/xingyanxiao/article/details/47055973

    一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
    因此,Fibonacci_5 。f(1)=1,f(2)=2。

    代码略。

  3. 兔子问题

    已知第一个月有一对刚出生的兔子,从出生第三个月起,一对兔子每个月可以生一对小兔子。假如没有发生死亡,则第一个月开始,第N个月后会有多少对?

    这里以对为单位,从第一个月开始,每个月总共的兔子数量就是1, 1, 2, 3, 5, 8, 13……可以看出前两个月为1,从第三个月开始,当月的数量为前两个月数量之和,所以 f(n) = f(n - 1) + f(n - 2)(n > 2)。同时f(1) = 1, f(2) = 1。

    代码实现同标准数学问题。

类似斐波那契问题还有很多,注意递推公式的推导即可。

斐波那契数列兔子问题是一个经典的数学问题。根据斐波那契数列定义,兔子的对数符合斐波那契数列的规律。斐波那契数列是指从第三项开始,每一项都是前两项的和。在兔子问题中,假设从出生后的第3个月起,每个月都会生一对兔子,且小兔子长到第3个月后每个月又生一对兔子。按照这个规律推算下去,可以得到兔子对数符合斐波那契数列。 在Java编程中,可以使用斐波那契数列来解决兔子问题。通过编写相应的代码,可以计算出第n个月有多少对兔子。 通过斐波那契数列的原理,我们可以推导出一个公式来计算第n个月的兔子对数。这个公式是:F(n) = F(n-1) + F(n-2),其中F(n)表示第n个月的兔子对数,F(n-1)表示第n-1个月的兔子对数,F(n-2)表示第n-2个月的兔子对数。通过递归或循环的方式,可以计算出第n个月的兔子对数。 总结起来,斐波那契数列兔子问题是一个有趣的数学问题,兔子的对数符合斐波那契数列的规律。在Java编程中,可以使用斐波那契数列的原理来解决兔子问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [斐波那契数列问题(兔子问题)](https://blog.youkuaiyun.com/Hedong_ling/article/details/115481125)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [java编程经典案例之基于斐波那契数列解决兔子问题实例](https://download.youkuaiyun.com/download/weixin_38660108/12770686)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [斐波那契问题(兔子问题)](https://blog.youkuaiyun.com/m0_63794226/article/details/127469693)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值