> 文档中心 > [JavaSE] 递归

[JavaSE] 递归

目录

方法递归

💬 递归的概念

💬 递归执行过程分析

💬 执行过程图

💬 递归练习

💬 递归小结

  

上一篇


   

疫情当前,大家要做好防护哦。

带好口罩了嘛?

那么大家跟着Nick来学习递归的知识!

  

方法递归

💬 递归的概念

   

🔴  一个方法在执行过程中调用自身, 就称为 "递归"。递归相当于数学上的 "数学归纳法", 有一个起始条件, 然后有一个递推公式。

     

🔴 简单理解递归:大问题转化为小问题。因为两者处理方式是一样的。

1、要调用自己本身

2、要有一个趋近于终止的条件

3、倒推出 递归的公式(重要)

   

🔴 例如, 我们求 N! 起始条件: N = 1 的时候, N! 为 1. 这个起始条件相当于递归的结束条件. 递归公式: 求 N! , 直接不好求, 可以把问题转换成 N! => N * (N-1)!

      

📝 代码示例: 递归求 N 的阶乘

import java.util.Scanner;public class 阶乘 {    public static void main(String[] args) { Scanner src =new Scanner(System.in); int  n = src.nextInt(); System.out.println(Factorial(n));    }    public  static int Factorial(int n){ if(n == 1){     return 1; }else{      return n*Factorial(n-1); }    }}

     

       

💬 递归执行过程分析

public class Demo {    public static void main(String[] args) { int n = 5; int ret = factor(n); System.out.println("ret = " + ret);    }    public static int factor(int n) { System.out.println("函数开始, n = " + n); if (n == 1) {     System.out.println("函数结束, n = 1 ret = 1");     return 1; } int ret = n * factor(n - 1); System.out.println("函数结束, n = " + n + " ret = " + ret); return ret;    }    // 执行结果//    函数开始, n = 5//    函数开始, n = 4//    函数开始, n = 3//    函数开始, n = 2//    函数开始, n = 1//    函数结束, n = 1 ret = 1//    函数结束, n = 2 ret = 2//    函数结束, n = 3 ret = 6//    函数结束, n = 4 ret = 24//    函数结束, n = 5 ret = 120//    ret = 120}

     

💬 执行过程图

  

🔴 关于 "调用栈" 方法调用的时候, 会有一个 "栈" 这样的内存空间描述当前的调用关系,称为调用栈。

      

🔴 每一次的方法调用就称为一个 "栈帧", 每个栈帧中包含了这次调用的参数是哪些, 返回到哪里继续执行等信息。后面我们借助 IDEA 很容易看到调用栈的内容

   

💬 递归练习

📝 代码示例1 按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)

   

import java.util.Scanner;//按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)public class 拆分 {    public static void main(String[] args) { Scanner src =new Scanner(System.in); int  n = src.nextInt(); split(n);    }    public static void split(int n){ if(n<10){     System.out.print(n%10+" "); }else{     split(n/10);     System.out.print(n%10+" "); }    }}

          

      


📝 代码示例2 递归求 1 + 2 + 3 + ... + 10

      

import java.util.Scanner;public class 累加 {    public static void main(String[] args) { Scanner src =new Scanner(System.in); int  n = src.nextInt(); System.out.println(sum(n));    }    public static int sum(int n){ if(n == 1){     return 1; }else{     return n+sum(n-1); }    }}

     

       


📝 代码示例3 写一个递归方法,输入一个非负整数,返回组成它的数字之和. 例如,输入 1729, 则应该返回1+7+2+9, 它的和是19。

     

import java.util.Scanner;//写一个递归方法,输入一个非负整数,返回组成它的数字之和.public class 拆分 {    public static void main(String[] args) { Scanner src =new Scanner(System.in); int  n = src.nextInt(); System.out.print(splitSum(n));    }    public static int splitSum(int n){ if(n<10){     return n; }else{     return n%10+splitSum(n/10); }    }}

     

     


📝 代码示例4 求斐波那契数列的第 N 项

   

原始版本

import java.util.Scanner;public class fbnq {    //求斐波那契数列的第 N 项    public static void main(String[] args) { Scanner src =new Scanner(System.in); int  n = src.nextInt(); System.out.println(fbnq(n));    }    public static int fbnq(int n){ if(n == 1 || n ==2){     return 1; }else{     return fbnq(n-1)+fbnq(n-2); }    }}

  

🔵 当我们求 fib(40) 的时候发现, 程序执行速度极慢,原因是进行了大量的重复运算,可以使用循环的方式来求斐波那契数列问题, 避免出现冗余运算

  

改良版本

import java.util.Scanner;public class fbnq {    //求斐波那契数列的第 N 项    public static void main(String[] args) { Scanner src =new Scanner(System.in); int  n = src.nextInt(); System.out.println(fbnq1(n));    }    public static int fbnq1(int n){ if(n == 1 || n==2){     return 1; }else{     int f1 = 1;     int f2 = 1;     int f3= 0;     for (int i = 3; i <=n; i++) {  f3=f1+f2;  f1=f2;  f2=f3;     }     return f3; }    }}

   

🔵此时程序的执行效率大大提高了


   

💬 递归小结

💠 递归是一种重要的编程解决问题的方式。

  

💠 有些问题天然就是使用递归方式定义的(例如斐波那契数列, 二叉树等), 此时使用递归来解就很容易。

  

💠 有些问题使用递归和使用非递归(循环)都可以解决, 那么此时更推荐使用循环, 相比于递归, 非递归程序更加高效。

     

未完待续
下一篇