• 算法 数据结构 斐波那契数列 递归实现斐波那契数列 斐波那契递归的优化 斐波那契数列递归求解 多路递归实现 斐波那契算法系列 数据结构(十一)


    1. 什么是斐波那契数列

    • 之前的例子是每个递归函数只包含一个自身的调用,这称之为 single recursion

    • 如果每个递归函数例包含多个自身调用,称之为 multi recursion

    递推关系

    f(n) = \begin{cases} 0 & n=0 \\ 1 & n=1 \\ f(n-1) + f(n-2) & n>1 \end{cases}

    下面的表格列出了数列的前几项

    F0F1F2F3F4F5F6F7F8F9F10F11F12F13
    01123581321345589144233

    多路递归斐波那契代码实现1:

    1. package com.nami.algorithm.study.day07;
    2. /**
    3. * beyond u self and trust u self.
    4. *
    5. * @Author: lbc
    6. * @Date: 2023-09-06 9:29
    7. * @email: 594599620@qq.com
    8. * @Description: keep coding
    9. */
    10. public class Fibonacci {
    11. /**
    12. * 出现问题的,计算 n= 88 根本算不出来。多路递归一直在循环里面了。出不来 --!
    13. * @param n
    14. * @return
    15. */
    16. public static int calculate(int n) {
    17. if (n == 0) {
    18. return 0;
    19. }
    20. if (n == 1) {
    21. return 1;
    22. }
    23. int f1 = calculate(n - 1);
    24. int f2 = calculate(n - 2);
    25. return f1 + f2;
    26. }
    27. public static void main(String[] args) {
    28. // 时间复杂度: 2*f(n+1) -1
    29. // E(1.618N次方)
    30. System.out.println(calculate(88));
    31. }
    32. }

      非递归实现2 --- LeetCode 70. 爬楼梯 计算爬楼梯共计多少种方法可达_不努力就种地~的博客-CSDN博客

      之前写的爬楼梯解决方案:

    1. public static int climbStairs(int n) {
    2. int[] dp = new int[n + 1];
    3. dp[0] = 1;
    4. dp[1] = 1;
    5. for(int i = 2; i <= n; i++) {
    6. dp[i] = dp[i - 1] + dp[i - 2];
    7. }
    8. return dp[n];
    9. }

    这种方法直接用数组去存储前面计算的值,不用重复计算。没有出现上面n=88出现的计算缓慢问题

    递归优化方案:

                           使用数组,存储之前计算的数据,减少计算次数。妙哉

    1. package com.nami.algorithm.study.day07;
    2. import java.util.Arrays;
    3. /**
    4. * beyond u self and trust u self.
    5. *
    6. * @Author: lbc
    7. * @Date: 2023-09-06 9:29
    8. * @email: 594599620@qq.com
    9. * @Description: keep coding
    10. */
    11. public class FastFibonacci {
    12. /**
    13. * 出现问题的,计算 n= 100000
    14. * 出现异常 StackOverflowError
    15. * 方法层级太深,会导致栈溢出
    16. *
    17. * @param n
    18. * @return
    19. */
    20. public static int calculate(int n) {
    21. // 初始化缓存
    22. // ==>记忆法
    23. // 空间换时间
    24. int[] cache = new int[n + 1];
    25. // 填充-1 标识未该值为计算
    26. Arrays.fill(cache, -1);
    27. cache[0] = 0;
    28. cache[1] = 1;
    29. return fibonacci(n, cache);
    30. }
    31. /**
    32. * 时间复杂度: O(n)
    33. * 增加额外空间成本
    34. *
    35. * @param n
    36. * @param cache
    37. * @return
    38. */
    39. private static int fibonacci(int n, int[] cache) {
    40. if (cache[n] != -1) {
    41. return cache[n];
    42. }
    43. int f1 = fibonacci(n - 1, cache);
    44. int f2 = fibonacci(n - 2, cache);
    45. cache[n] = f1 + f2;
    46. return cache[n];
    47. }
    48. public static void main(String[] args) {
    49. // n=88也有问题,出现-值
    50. // -2092787285
    51. System.out.println(calculate(88));
    52. }
    53. }

    使用数组进行优化,也有一个问题,数组只有n-1, n-2两个值有用。对于计算之后,存储前面n-3的值没有了意义;
     

    优化2 ==>尾递归:

                                尾递归(防止栈溢出) +  只取n-1, n-2的值流转

    1. package com.nami.algorithm.study.day07;
    2. /**
    3. * 尾递归 斐波那契数列
    4. * beyond u self and trust u self.
    5. *
    6. * @Author: lbc
    7. * @Date: 2023-09-06 9:29
    8. * @email: 594599620@qq.com
    9. * @Description: keep coding
    10. */
    11. public class TailRecFibonacci {
    12. /**
    13. * @param n
    14. * @return
    15. */
    16. public static int calculate(int n) {
    17. return fibonacci(n, 0, 1);
    18. }
    19. private static int fibonacci(int n, int first, int second) {
    20. if (n == 0) {
    21. return first;
    22. }
    23. if (n == 1) {
    24. return second;
    25. }
    26. return fibonacci(n - 1, second, first + second);
    27. }
    28. public static void main(String[] args) {
    29. // n=47,出现-值
    30. // -1323752223
    31. // 18 3631 1903 + 11 3490 3170
    32. // n= 46 + n=45
    33. // int 最大值 21 4748 3647
    34. System.out.println(calculate(46));
    35. }
    36. }

    为什么斐波那契数列会出现负值

          当n=88时,结果等于负数。排查发现:当n=46是正常的,n=47时,前面两个值的相加已经超过了int最大值int.max_value= 21 4748 3647 所以出现负数

    如何根本上解决爆栈问题

                                       递归转for or while循环解决问题。

  • 相关阅读:
    全球人口突破80亿!免费分享全球人口分布数据
    Opencv(C++)笔记--打开摄像头、保存摄像头视频
    Docker知识总结 (五) Dockerfile
    ARM资源记录《AI嵌入式系统:算法优化与实现》第八章(暂时用不到)
    SpringBoot SpringBoot 原理篇 1 自动配置 1.15 自动配置原理【1】
    Mac安装brew及前端环境「亲测有效」
    微信小程序查询接口
    C语言之练习题
    MobPush数智化推送,精准定位万圣节狂欢年轻一族
    如何在FPGA中构建数控振荡器 (NCO)
  • 原文地址:https://blog.csdn.net/qq_33919114/article/details/132729728