方法递归介绍及简单练习
递归的概念
一个方法在执行过程中调用自身,就称为递归
注意: 调用重载方法不是递归,不能光看方法名字
递归的关键: 方法调用时,程序会停在方法调用处,直到方法返回继续执行
递归的使用场景
- 一个问题可拆分为若干个子问题的解
- 拆分后的子问题与原问题除问题规模不同,解决思路相同
- 存在递归的终止条件
注意: 所谓终止条件就是不借助任何其他函数,就能直接知道求出问题答案
如何写出递归函数
思路: 在写递归函数的时候不要纠结函数内部是如何实现,我们需要关注的是这个函数实现了什么功能,即这个函数的语义,我们就假设这个方法已经写好,我们只需要去调用它即可
例如:
public static void main(String[] args) {//函数功能:求1到n的阶乘
int num=10;
int ret=factor(num);
System.out.println(ret);
}
public static int factor(int num){
if(num==1){//终止条件
return 1;
}
return num*factor(num-1);//我只知道num本身的指,剩下的(num-1)的阶乘交给factor函数
}
总结:
递归代码=终止条件+当前不借助任何方法就能实现的步骤+剩下的问题利用相同的方法解决
递归练习题
- 青蛙跳台阶问题: 一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法
public static void main(String[] args) {
System.out.println("请输入正整数N:");
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
System.out.println("一共有"+fun(n)+"种跳法");
}
public static int fun(int num){
if(num==1 || num==0){
return 1;//终止条件
}
if (num==2){
return 2;
}
return fun(num-1)+fun(num-2);//当要跳上n级台阶时,要么从n-1级台阶跳上,要么从n-2级台阶跳上
}
2.递归求解汉诺塔问题
public static void main(String[] args) {
hnooi(3,"塔1","塔2","塔3");
}
private static void hnooi(int n,String a,String b,String c) {
if(n==1){
System.out.println(a+"移动到"+c);
}else{
hnooi(n-1,a,c,b);//将n-1个圆盘从a塔移动到b塔
System.out.println(a+"移动到"+c);//将第n个圆盘从a塔移动到c塔
hnooi(n-1,b,a,c);//将n-1个圆盘从b塔移动到c塔
}
}
3.递归求斐波那契数列的第 N 项
public static void main(String[] args) {
System.out.println("请输入正整数N:");
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
System.out.println(feibo(n));
}
public static int feibo(int num){
if(num==1 || num==2){
return 1;
}
return feibo(num-1)+feibo(num-2);
}
4.写一个递归方法,输入一个非负整数,返回组成它的数字之和,如输入1234,返回10.
public static void main(String[] args) {
System.out.println("请输入一个非负整数:");
Scanner scanner=new Scanner(System.in);
int num=scanner.nextInt();
System.out.println(sum(num));
}
public static int sum(int num){
//当前数为个位,可以直接知道他本身
if(num<10){
return num;
}
//此时num至少是个两位数,只能知道它个位上的数字,剩下的数字交给sum函数
return num%10+sum(num/10);
}
5.按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4) (递归)
public static void main(String[] args) {
print(1234);
}
public static void print(int num){//按高位到低位的顺序打印数字的每一位
//当前数为个位,可以直接知道他本身
if(num<10){
System.out.print(num+" ");
return;
}
//当前数字至少是个两位数,只能知道他的个位
//高位交给print函数
print(num/10);
System.out.print(num%10+" ");
递归小结
1.递归是一种重要的编程解决问题的方式.
2.有些问题天然就是使用递归方式定义的(例如斐波那契数列, 二叉树等), 此时使用递归来解就很容易.
3.有些问题使用递归和使用非递归(循环)都可以解决. 那么此时更推荐使用循环, 相比于递归, 非递归程序更加高效