【算法】斐波那契数列

学而不思则罔,思而不学则殆


斐波那契数列公式

公式如下:
F ( n ) = { 1 n=0,1 F ( n − 1 ) + F ( n − 2 ) n>2 F(n)= \begin{cases} 1 & \text{n=0,1}\\ F(n-1) + F(n-2) & \text{n>2}\\ \end{cases} F(n)={1F(n1)+F(n2)n=0,1n>2

这种很容易有两种解法:递归和非递归

递归一

    private static long fac(long n) {
        if (n == 0 || n == 1) {
            return 1;
        }
        return fac(n - 1) + fac(n - 2);
    }

代码只有几行,很好理解,但是呢,运行效率不怎么行,后面会跟非递归方法对比一下。

递归二

    private static long fac2(long n) {
        HashMap<Long, Long> map = new HashMap<>();
        map.put(0L, 1L);
        map.put(1L, 1L);
        return fac22(n, map);
    }

    private static long fac22(long n, HashMap<Long, Long> map) {
        if (map.containsKey(n)) {
            return map.get(n);
        }
        long result = fac22(n - 1, map) + fac22(n - 2, map);
        map.put(n, result);
        return result;
    }

该方法也是递归实现,只是会通过map保存已经计算的结果,理论上所有的求值智慧计算一遍就不会再重复计算了。方法对比第一种方法,会减少很多的计算量。减少了第一种方法的重复计算部分,大大减少了时间消耗。

非递归 - 动态规划

动态规划(Dynamic Programming,DP)是运筹学的一个分支,是求解决策过程最优化的过程。

基本思想:问题的最优解如果可以由子问题的最优解推导得到,则可以先求解子问题的最优解,在构造原问题的最优解;若子问题有较多的重复出现,则可以自底向上从最终子问题向原问题逐步求解。
使用条件:可分为多个相关子问题,子问题的解被重复使用
已经求得的子问题可以通过一维数组,二维数组保留下来,使用的时候可以直接获取。

    //动态规划
    private static long fac3(long n) {
        if (n == 1 || n == 0) {
            return 1;
        }
        HashMap<Long, Long> map = new HashMap<>();
        map.put(0L, 1L);
        map.put(1L, 1L);
        long index = 2L;
        while (index <= n) {
            map.put(index, map.get(index - 1) + map.get(index - 2));
            index++;
        }
        return map.get(n);
    }

思路:通过map保存下之前的结果,自底向上求解

三种算法对比

算法\时间递归一递归二动态规划
0010
1000
10001
20010
30402
4046800
45500301
46784301
471270701
482005611
493244001
505237111
60-01
70-11
80-00
90-01
100-11
200-11
500-12
1000-11

可以看到第一种算法当求50的数的时候时间就要50多秒了,后面直接不行了,而第二种和第三种算法几乎一直是很低的一个事件消耗,只是有 O ( n ) O(n) O(n)
的空间消耗。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【问题描述】 【问题描述】编写函数f,功能是用递归的方法求斐波那契数列的第n项,函数原型为 int f(int n),在主函数中输入一个正整数n,调用函数f求出斐波那契数列的第n项,并在主函数中输出。 斐波那契数列:1,1,2,3,5,8,13,21…… 【输入形式】3 【输出形式】2 【样例输入】6 【样例输出】8 【问题描述】编写函数f,功能是用递归的方法求斐波那契数列的第n项,函数原型为 int f(int n),在主函数中输入一个正整数n,调用函数f求出斐波那契数列的第n项,并在主函数中输出。 斐波那契数列:1,1,2,3,5,8,13,21…… 【输入形式】3 【输出形式】2 【样例输入】6 【样例输出】8 【问题描述】编写函数f,功能是用递归的方法求斐波那契数列的第n项,函数原型为 int f(int n),在主函数中输入一个正整数n,调用函数f求出斐波那契数列的第n项,并在主函数中输出。 斐波那契数列:1,1,2,3,5,8,13,21…… 【输入形式】3 【输出形式】2 【样例输入】6 【样例输出】8 【问题描述】编写函数f,功能是用递归的方法求斐波那契数列的第n项,函数原型为 int f(int n),在主函数中输入一个正整数n,调用函数f求出斐波那契数列的第n项,并在主函数中输出。 斐波那契数列:1,1,2,3,5,8,13,21…… 【输入形式】3 【输出形式】2 【样例输入】6 【样例输出】8 斐波那契数列:1,1,2,3,5,8,13,21…… 【输入形式】3 【输出形式】2 【样例输入】6 【样例输出】8
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值