• 数据结构之:递归思想


    (一)递归概念
    将复杂问题 递推分解为最简问题 然后将结果回归的过程
    Windows - Linux
    Linux = Linux is not Unix
    使用方法: 自己调用自己
    (二)斐波那契数列
    兔子问题
    有一对大兔子 每个月繁衍 一对小兔子(一公一母)
    小兔子 每个月生长为 大兔子
    现有一对小兔子 一年后 有多少对?
    M1 1 A
    M2 1 A~
    M3 2 A->B
    M4 3 A->C + B~
    M5 5 A->D + B->E + C~
    M6 8 A->F + B->G + C->H + D~ + E~
    当前的所有兔子 = 上个月的所有兔子 + 这个月新生的兔子(可以繁衍的兔子)
    = 上个月的所有兔子数量 + 上上个月的所有兔子数量(经过了一个月的生长周期)
    Mn = M(n-1) + M(n-2)
    M5 = M4 + M3
    = (M3+M2) + (M2+M1)
    = (M2+M1 + M2) + (M2+M1)
    = 1+1+1 + 1+1 = 5
    M1=1 M2=1
    使用方式:
    1 )推导出递推公式 —— 找规律
    2 )找到递推的出口 —— 找出口
    1. public static int fib(int N) {
    2. if (N == 1) return 1;
    3. if (N == 2) return 1;
    4. System.out.println("求第" + N + "个月的兔子数量");
    5. System.out.println("转化为求第" + (N - 1) + "个月和第" + (N - 2) + "个月的兔子数量");
    6. return fib(N - 1) + fib(N - 2);
    7. }
    大部分递归 可以转化为迭代处理
    Make it work,Make it right,Make it fast
    思路:使用数组存储,通过 n-1 n-2 的值进行计算

    1. public static int fib1(int N) {
    2. // 6 —— 0 1 2 3 4 5
    3. // fib(0) = 0 有时需要处理
    4. if (N <= 1) return 1;
    5. int[] arr = new int[N];
    6. arr[0] = 1;
    7. arr[1] = 1;
    8. for (int i = 2; i < arr.length; i++) {
    9. arr[i] = arr[i - 1] + arr[i - 2];
    10. }
    11. return arr[N - 1];
    12. }
    递归经典应用之汉诺塔
    汉诺塔
    印度的恒河 瓦拉那西 诞生婆罗门教
    放了三根柱子,其中一个根柱子上放了 64 个圆盘
    需要将全部圆盘 移动到另一根柱子上
    并且 每次只能移动一个 移动过程中 小圆盘必须在大圆盘之上
    为何不可完成?
    分析:
    一个圆盘 A->C
    两个圆盘 A->B A->C B->C
    三个圆盘 A->C A->B C->B ( 把前两个圆盘 从 A 移动到 B)
    A->C ( 移动最大的圆盘 )
    B->A B->C A->C ( 再把前两个圆盘 从 B 移动到 C)
    N 个圆盘
    先把前 N-1 个圆盘 A 移动到 B ( 经由 C)
    再把最大的圆盘 A 移动到 C
    最后把前 N-1 个圆盘 B 移动到 C ( 经由 A)
    移动次数
    H(1) = 1
    H(2) = 3
    H(3) = H(2) + 1 + H(2) = 7
    H(4) = 7 + 1 + 7 = 15
    H(N) = H(N-1) + 1 + H(N-1) = 2^N - 1
    1. // 四个参数 有n个圆盘 需要从A柱子移动到C 经由B
    2. // 起始 中间 终点
    3. public static void hanoi(int n, char A, char B, char C) {
    4. // 出口
    5. if (n == 1) {
    6. System.out.println(A + "->" + C);
    7. return;
    8. }
    9. // 先把前N-1个圆盘 从A移动到B (经由C)
    10. // 再把最大的圆盘 从A移动到C
    11. // 最后把前N-1个圆盘 从B移动到C (经由A)
    12. hanoi(n - 1, A, C, B);
    13. System.out.println(A + "->" + C);
    14. hanoi(n - 1, B, A, C);
    15. }
    1. public class Fibonacci {
    2. public static void main(String[] args) {
    3. System.out.println(fib1(6));
    4. }
    5. // 返回第n个月有多少只兔子
    6. public static int fib(int N) {
    7. if (N == 1) return 1;
    8. if (N == 2) return 1;
    9. System.out.println("求第" + N + "个月的兔子数量");
    10. System.out.println("转化为求第" + (N - 1) + "个月和第" + (N - 2) + "个月的兔子数量");
    11. return fib(N - 1) + fib(N - 2);
    12. }
    13. public static int fib1(int N) {
    14. // 6 —— 0 1 2 3 4 5
    15. // fib(0) = 0 有时需要处理
    16. if (N <= 1) return 1;
    17. int[] arr = new int[N];
    18. arr[0] = 1;
    19. arr[1] = 1;
    20. for (int i = 2; i < arr.length; i++) {
    21. arr[i] = arr[i - 1] + arr[i - 2];
    22. }
    23. return arr[N - 1];
    24. }
    25. }
    1. public class Hanoi {
    2. public static void main(String[] args) {
    3. //三个圆盘 A->C A->B C->B (把前两个圆盘 从A移动到B)
    4. // A->C (移动最大的圆盘)
    5. // B->A B->C A->C (再把前两个圆盘 从B移动到C)
    6. hanoi(3, 'A', 'B', 'C');
    7. }
    8. // 四个参数 有n个圆盘 需要从A柱子移动到C 经由B
    9. // 起始 中间 终点
    10. public static void hanoi(int n, char A, char B, char C) {
    11. // 出口
    12. if (n == 1) {
    13. System.out.println(A + "->" + C);
    14. return;
    15. }
    16. // 先把前N-1个圆盘 从A移动到B (经由C)
    17. // 再把最大的圆盘 从A移动到C
    18. // 最后把前N-1个圆盘 从B移动到C (经由A)
    19. hanoi(n - 1, A, C, B);
    20. System.out.println(A + "->" + C);
    21. hanoi(n - 1, B, A, C);
    22. }
    23. }
  • 相关阅读:
    MySQL事务(清晰易懂)
    docker部署django(uwsgi+nginx)
    【vue2第十四章】 插槽(普通插槽、具名插槽、作用域插槽语法)
    10月27日,每日信息差
    Javase --- 多线程复习
    C++中使用 min()函数/max()函数进行多数比较
    hystart++ 出炉
    FT2004(D2000)开发实战之PBF配置
    编译报错:undefined reference to `TIFFReadDirectory@LIBTIFF_4.0‘解决方法
    泛微 E-Office download.php 任意文件读取漏洞
  • 原文地址:https://blog.csdn.net/KAITUOZHEMJ/article/details/127955348