• Java算法——递归思想


    描述
    递归(recursion):程序调用自身的编程技巧。

    递归满足2个条件:
    1)有反复执行的过程(调用自身)
    2)有跳出反复执行过程的条件(递归出口)

    递归与栈的关系
    下面演示的是求n的阶乘

    int Factorial(int n){ 
    if (n == 0) return 1; 
    return n * Factorial(n - 1);
    }

    常常听到 “递归的过程就是出入栈的过程”,这句话怎么理解?我们以上述代码为例,取 n=3,则过程如下:

    第 1~4 步,都是入栈过程,Factorial(3)调用了Factorial(2),Factorial(2)又接着调用Factorial(1),直到Factorial(0);

    第 5 步,因 0 是递归结束条件,故不再入栈,此时栈高度为 4,即为我们平时所说的递归深度;

    第 6~9 步,Factorial(0)做完,出栈,而Factorial(0)做完意味着Factorial(1)也做完,同样进行出栈,重复下去,直到所有的都出栈完毕,递归结束。

    每一个递归程序都可以把它改写为非递归版本。我们只需利用栈,通过入栈和出栈两个操作就可以模拟递归的过程,二叉树的遍历无疑是这方面的代表。

    但是并不是每个递归程序都是那么容易被改写为非递归的。某些递归程序比较复杂,其入栈和出栈非常繁琐,给编码带来了很大难度,而且易读性极差,所以条件允许的情况下,推荐使用递归。

    示例题目
    1.有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少对?请使用递归和非递归实现。

    import java.util.Scanner;
    
    public class Main{
    /*
    * 兔子的规律为数列1,1,2,3,5,8,13,21.... 这是一个菲波拉契数列问题 {斐波拉契数列原理:除开前两项 后面每位数等于前两项相加之和}
    * 1.通过中间值来保存上一月兔子的和 2.在将上一月兔子这一月兔子相加 得到下一月数量和
    */
    
    // 非递归
    public static void f1(int month) {
    int rabbit = 1; // 上月兔子的数量和
    int newRabbit = 1; // 这一月生成兔子的数量和
    int count; // 中间值 用来存数量的
    if (month == 1) {
    System.out.println("第1月兔子 1 对");
    } else if (month == 2) {
    System.out.println("第2月兔子 1 对");
    } else {
    // 从第三月起
    for (int i = 3; i <= month; i++) {
    count = newRabbit;
    newRabbit = rabbit + newRabbit;
    rabbit = count;
    }
    System.out.println("第" + month + "月兔子 " + newRabbit + " 对");
    }
    }
    
    // 递归
    public static int f2(int month) {
    if (month == 1 || month == 2) {
    return 1;
    }
    // 上一个月的兔子数
    int rabbit1 = f2(month - 1);
    // 上一个月的前一个月兔子数
    int rabbit2 = f2(month - 2);
    return rabbit1 + rabbit2;
    }
    
    public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int month = sc.nextInt();
    f1(month);
    System.out.println("============");
    System.out.println("第" + month + "月兔子 " + f2(month) + " 对");
    }
    }

    2.十进制转二进制

    import java.util.Scanner;
    
    /* 
    * 十进制转二进制
    */
    public class Main {
    // 非递归
    public static void f1(int n) {
    int t = 0;
    int bin = 0;
    int r = 0;
    while (n != 0) {
    r = n % 2;
    n = n / 2;
    bin += r * Math.pow(10, t);
    t++;
    }
    System.out.println(bin);
    }
    
    // 递归
    public static void f2(int n) {
    if (n / 2 == 0) {
    System.out.print(n % 2);
    } else {
    f2(n / 2);
    System.out.print(n % 2);
    }
    
    }
    
    public static void main(String[] args) {
    System.out.println("请输入一个非负的十进制整数:");
    Scanner sc = new Scanner(System.in);
    int number = sc.nextInt();
    if (number < 0) {
    System.out.println("不符合要求");
    } else {
    System.out.print("对应的二进制:");
    f1(number);
    System.out.println("=================");
    System.out.print("对应的二进制:");
    f2(number);
    }
    }
    }
  • 相关阅读:
    Fiddler捕获抓取 App端数据包
    配置Java SSL 访问网站证书
    win10+vs2015+opencv3.0 x86/x64配置(debug+release)
    VMware虚拟机安装CentOS 7并搭建lamp服务器环境
    ubuntu18.04下eclipse配置及快捷方式创建
    ubuntu 安装vmware workstation
    linux安装出错
    [集合]java中的 可变参数
    泛型
    [集合]List
  • 原文地址:https://www.cnblogs.com/ericz2j/p/10908794.html
Copyright © 2020-2023  润新知