递归
一个函数在其定义或说明中有直接或间接调用自身的一种方法。
它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
看文字很迷,我在下边例子做具体说明,相信大家看完就大概理解什么是递归了
1.实现代码: 递归求 N 的阶乘
//实现代码: 递归求 N 的阶乘
import java.util.*;
public class work992 {
public static void main(String[] args) {
System.out.println("输入需要计算哪个数的阶乘:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println("结果为:" + factor(n));
}
public static int factor(int x) {
if (x == 1) {
return 1;
}
return x*factor(x-1);
}
}
直接求5的阶乘,可能我们都会手算,那如果是100呢?
100!我们不会做,但是我们知道100! = 100 * 99!,那我们要是知道99!这个问题就解决了,所以问题转换为求99!,而99! = 99 * 98! ,问题又转化为求98!……一直到求2!,2! = 2*1!,而1!我们知道,就是它本身。
所以,我们最后得到了2!,得到了3!……得到了99!,100!的答案我们也就得到了
对于这个问题,边界条件就是n = 1
停止,前进段是:如果n 不到1,就求n-1
的阶乘。返回段是最终n的阶乘结果。
下边2 - 5例子和本例子完全一样,试着自己理解一下,不再解释。
2. 实现代码: 递归求 1 加到指定数
import java.util.*;
public class work992 {
public static void main(String[] args) {
System.out.println("从1加到指定数:");
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
System.out.println("结果为:" + sum(a));
}
public static int sum(int x ) {
if (x == 1) {
return 1;
}
return x+sum(x-1);
}
}
3.实现代码: 按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)
import java.util.*;
public class work992 {
public static void main(String[] args) {
System.out.println("输入数字:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println("每一位数字分别为:");
fun(n);
}
public static void fun(int x){
if(x>9){
fun(x/10);
}
System.out.print(" "+x%10+" ");
}
}
4.写一个递归方法,输入一个非负整数,返回组成它的数字之和.
import java.util.*;
public class work992 {
public static void main(String[] args) {
System.out.println("输入数字:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println("结果为:"+sum(n));
}
public static int sum(int x){
if(x<10){
return x;
}
return x % 10 + sum(x / 10);
}
}
5.实现代码: 求斐波那契数列的前 N 项
public static void main(String[] args) {
System.out.println("输入数字:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 1;i <= n;i++){
System.out.print(fib(i)+" ");
}
}
public static int fib(int x) {
//三目运算与底下的if判断语句效果完全一样
return (x == 1 || x == 2)?1:fib(x-1) + fib(x-2);
// if (x == 1 || x == 2) {
// return 1;
// }
// return fib(x-1) + fib(x-2);
}
6.实现代码: 求解汉诺塔问题(递归实现)
已知:
一共有N阶汉诺塔需要从A移动到C,初始位置在A,终态位置在C,B是中转站,最底下盘子为1号。
要把1号盘子移动过去,需要1号上边N-1个先移动到B,然后将1号移动到C,再把N-1个从B移动到C。
而要把N-1个盘子从A到B移动,可以看作一个新的汉诺塔问题,此问题初始位置在A,终态位置在B,C是中转站,一共盘子为N-1个
新的汉诺塔问题要把一号盘子移动过去,需要他上边N-2个先移动到中转位置C,然后将1号移动到B,再把N-2个从C移动到B------N-2个的移动也是一样的道理,很明显的一个递归
代码思路:
要让我们自己想搬运的过程,肯定做不到。但是我们知道所有汉诺塔问题的边界条件都是一致的 – 把1号盘子,从初始位置,借助中转,搬到终态位置。具体过程怎么搬的,我们不用考虑,计算机会去做。
因此,我们把上边N-1个盘子看作一个整体,下边一个看作另一个整体。
重新来看这个问题的话,我们只需要知道,让上边N-1个借助C先移动到B,然后因为只剩下一个,所以直接将1号移动到C,再把N-1个从B,借助A,移动到C就可以实现题目要求,而不用关心他到底如何移动。
递归函数为:
hano(x-1,from,to,enter);
hano(x-1,enter,from,to);
每次的返回段为当前盘子的移动轨迹。
import java.util.*;
public class work992 {
public static void main(String[] args) {
System.out.println("输入汉诺塔阶数(默认为A,B,C三个塔柱),最底下盘子为1号:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
hano(n, "A", "B", "C");
}
public static void hano(int x, String from, String enter, String to) {
if (x == 1) {
System.out.println(" 从 " + from + " 到 " + to); //只剩一个盘子,直接从初始状态移动到终态位置
} else {
hano(x - 1, from, to, enter); //将A上的X-1个盘子移动到B上
System.out.println(" 从 " + from + " 到 " + to);
hano(x - 1, enter, from, to); //将B上的X-1个盘子移动到C上
}
}
}
7.实现代码: 青蛙跳台阶问题(提示, 使用递归)一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法
思路:首先考虑n等于0、1、2时的特殊情况,jump(0) = 0 ,jump(1) = 1 ,jump(2) = 2
然后,当n=3时,青蛙的第一跳有两种情况:跳1级台阶或者跳两级台阶,假如跳一级,那么 剩下的两级台阶就是jump(2);假如跳两级,那么剩下的一级台阶就jump(1),因此jump(3) = jump(2) + jump(1) 当n = 4时,jump(4) = jump(3) +jump(2),以此类推…可以联想到斐波那契数列, 即满足递归函数jump(n)=jump(n-1)+jump(n-2).
import java.util.Scanner;
public class work993 {
public static void main(String[] args) {
System.out.println("台阶总数:");
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println("" +jump(n));
}
public static int jump(int n) {
if(n == 0){
return 1;
}
if(n == 1){
return 1;
}
if(n == 2){
return 2;
}
return jump(n-1) + jump(n-2);
}
}