赞
踩
递归:递归就是在函数里调用函数本身。 基线条件和递归条件 1、基线条件:就是指结束调用的条件,避免形成无限循环。 2、递归条件:就是指函数调用自己的条件。 3、递归必须向基线条件逼近,否则就会出现无线递归。
一、打印问题
给出一个整数,使用递归打印它。
- public class Recursion {
- public static void main(String[] args) {
- Recursion.test(4);
- }
-
- public static void test(int a) {
- if (a > 2) {
- test(a-1);
- }
- System.out.println(a);
- }
- }
-
-
- 解读:
- 第一次调用test,创建一个栈,传入4,判断4是否会大于2,4大于2进行第二次调用,4-1
- 第二次调用test,创建一个栈,传入3,判断3是否会小于2,3大于2进行第三次调用,3-1
- 第三从调用test,创建一个栈,传入2,判断2是否会大于2,2等于2进行返回
- 第一次返回,销毁栈,打印2,
- 第二次返回,销毁栈,打印3
- 第三次返回,销毁栈,打印4
- 结束程序
-
- 2
- 3
- 4
二、累加问题
给出一个整数,使用递归求出它累加的和。
- public class Accumulation {
- public static void main(String[] args) {
- int a = Accumulation.test(3);
- System.out.println(a);
- }
-
- public static int test(int x) {
- if (x == 1) {
- return 1;
- } else {
- return x+test(x-1);
- }
- }
- }
-
-
- 解读:
- 1.在main中第一次调用test,创建第一层栈,传入3,判断是否等于1,3大于1,符合递归条件,进行第二次调用test,3-1
- 2.第二次调用test,创建第二层栈,传入2,判断是否等于1,2大于1,符合递归条件,进行第三次调用test,2-1
- 3.第三次调用test,创建第三层栈,传入1,判断是否等于1,1等于1,符合基线条件,进行返回
- 4.第三层栈,返回1
- 5.第二层栈,返回3,2+1
- 6.第一层栈,返回6,3+2+1
- 程序结束
-
- 6
三、阶层问题
给出一个整数,使用递归求出它的阶乘。
- public class Factorial {
- public static void main(String[] args) {
- int a = Factorial.test(5);
- System.out.println(a);
- }
-
- public static int test(int x){
- if (x == 1){ // 基线条件
- return 1;
- }else{ // 递归条件
- return test(x-1) * x;
- }
- }
- }
-
-
- 递归解读:
-
- 1. 在main中第一次调用test,创建第一层栈,传入5,判断是否等于1,5大于1,符合递归条件,进行第二次调用test,5-1
- 2. 第二次调用test,创建第二层栈,传入4,判断是否等于1,4大于1,符合递归条件,进行第三次调用test,4-1
- 3. 第三次调用test,创建第三层栈,传入3,判断是否等于1,3大于1,符合递归条件,进行第四次调用test,3-1
- 4. 第四次调用test,创建第四层栈,传入2,判断是否等于1,2大于1,符合递归条件,进行第五次调用test,2-1
- 5. 第五次调用test,创建第五层栈,传入1,判断是否等于1,1等于1,符合基线条件,进行返回
- 6. 第五层栈,销毁栈,返回1,return 1;
- 7. 第四层栈,销毁栈,返回2,return test(2-1) * 2;
- 8. 第三层栈,销毁栈,返回6,return test(3-1) * 3;
- 9. 第二层栈,销毁栈,返回24,return test(4-1) * 4;
- 10. 第一层栈,销毁栈,返回120,return test(24-1) * 5;
- 11. 程序结束
-
- 120
四、斐波那契
用递归求出斐波那契数1,1,2,3,4,5,8,13...给一个整数x,求出它的值是多少。
- public class Fibonacci {
- public static void main(String[] args) {
- int x = 4;
- int a = Fibonacci.test(x);
- if (a != -1){
- System.out.println("当x="+x+",对应的斐波那契是"+a);
- }
- }
-
- //思路分析:斐波那契是前两个数之和,且必须是整数。
- public static int test(int x) {
- if (x >= 1) { //斐波那契必须是整数
- if (x == 1 || x == 2) { //
- return 1;
- } else {
- return test(x - 1) + test(x - 2);
- }
- } else {
- System.out.println("要求输入的x必须是大于等于1的整数");
- return -1;
- }
-
- }
- }
-
-
- 解读:
- 第一次调用test方法,向方法传递整数x(x=4)
- 判断x是否大于等于1(因为斐波那契数不能小于1),小于1,输出提示信息,并返回-1
- 大于等于1,则在判断x是否是1或2,是1或2则返回1;(因为1和2的斐波那契数是1)
- 否则进行第二次第一个调用test,创建栈,传入3 + 第二次第二个调用test,创建栈,传入2
- 第二次第一个test,进行x是否大于等于1的判断,3>=1,在判断是否会等于1或2,3不等于1或2,
- 进行第三次第一个调用test,创建栈,传入2,+ 第三次第二个调用test,创建栈,传入1
- 第三次第一个test,进行x是否大于等于1的判断,2>=1,在判断是否会等于1或2,2等于1或2,进行返回
- 第三次第二个test,进行x是否大于等于1的判断,1>=1,在判断是否会等于1或2,1等于1或2,进行返回
- 第二次第二个test,进行x是否大于等于1的判断,2>=1,在判断是否会等于1或2,2等于1或2,进行返回
-
- 第三次第一个test,返回,1
- 第三次第二个test,返回1
- 第二次第一个test,返回2
- 第二次第二个test,返回1
- 第一次返回调用处,返回3
-
- 3
五、猴子吃桃问题
有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个。以后的每天猴子都吃其中的一半,然后再多吃一个。
当第10天时,想再吃时(还没有吃),发现只有一个桃子了。问最初有多少个桃子。
- public class MonkeyPeach {
- public static void main(String[] args) {
- int day = 1;
- int a = MonkeyPeach.test(day);
- if (a != -1) {
- System.out.println("第" + day + "天有" + a + "个桃");
- }
- }
-
- public static int test(int day) {
- if (day == 10) { // 第十天只有1个桃
- return 1;
- } else if (day >= 1 && day <= 9) { //天数必须在1-10天之内
- return (test(day + 1) + 1) * 2;
- } else {
- System.out.println("day必须在1-10之间");
- return -1;
- }
- }
- }
-
-
- 思路分析:逆推
- 1. day10 有 1个桃子
- 2. day9 有 (day10+1)*2=4 个桃子 4/2-1=1
- 3. day8 有 (day9+1)*2=10 个桃子 10/2-1=4
- 规律就是 前一天的桃子 = (后一天的桃子 +1)*2
-
- 输入天数可以获取当天桃子的个数,输入6
- 第一次调用test(6),创建栈,出传入6,判断是否等于10,6不等于10,在判断是否大于等于1且小于等于9,6大于等于1且小于等于9,进行第二次调用test
- 第二次调用test(6+1),创建栈,传入7,判断是否等于10,7不等于10,在判断是否大于等于1且小于等于9,7大于等于1且小于等于9,进行第三次调用test
- 第三次调用test(7+1),创建栈,传入8,判断是否等于10,8不等于10,在判断是否大于等于1且小于等于9,8大于等于1且小于等于9,进行第四次调用test
- 第四次调用test(8+1),创建栈,传入9,判断是否等于10,9不等于10,在判断是否大于等于1且小于等于9,9大于等于1且小于等于9,进行第五次调用test
- 第五次调用test(9+1),创建栈,传入10,判断是否等于10,10等于10,进行返回,返回1
- 第五次调用,return 1,返回1,销毁栈
- 第四次调用,return (1 + 1) * 2,返回4,销毁栈
- 第五次调用,return (4 + 1) * 2,返回10,销毁栈
- 第五次调用,return (10 + 1) * 2,返回22,销毁栈
- 第五次调用,return (22 + 1) * 2,返回46,销毁栈
- 程序结束
-
- 46
六、汉诺塔问题
把圆盘从a塔移动到c塔,且小于圆盘要在上面。
- public class HanoiTower {
- public static void main(String[] args) {
- Test test = new Test();
- test.move(5,'A', 'B', 'C');
- }
- }
-
- class Test{
- // num 表示要移动的个数,a,b,c 分别表示A塔 B塔 C塔
- public static void move(int num, char a, char b, char c){
- // 如果只有一个圆盘
- if (num == 1){
- System.out.println(a + "->" + c);
- }else{
- // 如果有多个圆盘,可以看成两个,最下面的和上面的所有圆盘(num-1)
- //(1)先移动上面所有的圆盘到b,借助c
- move(num-1, a, c, b);
- //(2)把最下面的这个圆盘,移动到c
- System.out.println(a + "->" + c);
- //(3)再把b塔的所有圆盘,移动到c,借助a
- move(num-1, b, a, c);
- }
- }
- }
-
- 汉诺塔解读:
- main创建第一层栈,第一次调用move,创建第二层栈,传入 3,A,B,C,判断3是否等于1,3不等于1,
- 则进行第二次调用move,创建第三层栈,传入 2,A,C,B,判断2是否等于1,2不等于1
- 则进行第三次调用move,创建第四层栈,传入 1,A,B,C,判断1是否等于1,1等于1,输出 A->C,销毁栈,返回第三层
- 第三层栈,输出 A->B,
- 第四次调用move,创建第四层栈,传入1,C,A,B,判断1是否等于1,1等于1,输出 C->B,销毁栈,返回第三层
- 销毁栈,返回到第二层
- 第二层栈,输出 A->C,
- 第二层栈,进行第五次调用move,创建第三层栈,传入2,B,A,C,判断2是否等于1,2不等于1
- 则进行第六次调用move,创建第四层栈,传入 1,B,C,A,判断1是否等于1,1等于1,输出 B->A,销毁栈,返回第三层
- 第三层栈,输出B->C
- 第三层,进行第七次调用move,创建第四层栈,传入1,C,B,A,判断1是否等于1,1等于1,输出 A->C,销毁栈,返回第三层
- 销毁栈,返回第二层
- 销毁栈,返回第一层调用处
- 结束程序
-
- A->C
- A->B
- C->B
- A->C
- B->A
- B->A
- C->A
▲表示输出
七、老鼠出迷宫问题
- public class Maze {
- public static void main(String[] args) {
- //创建迷宫,用二维数组表示 int[][] map = new int[8][7]
- //先规定 map数组的元素值:0表示可以走,1表示障碍物
- int[][] map = new int[8][7];
-
- // 设置障碍物
- //将最上面的一行和最下面的一行,全部设置为1
- for (int i = 0; i < 7; i++) {
- map[0][i] = 1;
- map[7][i] = 1;
- }
- //将最左面的一列和最右面的一列,全部设置为1
- for (int i = 0; i < 8; i++) {
- map[i][0] = 1;
- map[i][6] = 1;
- }
- map[3][1] = 1;
- map[3][2] = 1;
-
-
- // 输出地图
- System.out.println("====== 迷宫地图 ======");
- for (int i = 0; i < map.length; i++) {
- for (int j = 0; j < map[i].length; j++) {
- System.out.print(map[i][j] + " ");
- }
- System.out.println();
- }
-
-
- // 使用findWay给老鼠找路
- test t = new test();
- t.findWay(map,1,1);
- System.out.println("====== 找路情况如下 ======");
- for (int i = 0; i < map.length; i++) {
- for (int j = 0; j < map[i].length; j++) {
- System.out.print(map[i][j] + " ");
- }
- System.out.println();
- }
- }
- }
-
- // 使用递归回溯解决老鼠出迷宫
- // 1. findWay方法就是专门来找迷宫路径的
- // 2. 如果找到返回true,没有找到返回false
- // 3. map 就是二维数组,即表示迷宫
- // 4. x,y就是老鼠的坐标,初始化为 (1, 1)
- // 5. 因为是递归找路,所以先规定 map数组的各个值的含义
- // 0表示可以走,1表示障碍物,2表示可以走,3表示走过,但走不通是死路
- // 6. 当map[6][5]=2 就说明找到通路,就可以结束,否则就继续找。
- // 7. 先确定老鼠找路策略 下-> 右-> 上-> 左
- class test {
- public boolean findWay(int[][] map, int x, int y) {
- if (map[6][5] == 2) { //说明已经找到
- return true;
- } else {
- if (map[x][y] == 0) { //当前这个位置0,说明表示可以走
- // 我们可以假定走通
- map[x][y] = 2;
- // 使用找路策略,来确定该位置是否真的可以走通
- // 下-> 右-> 上-> 左
- if (findWay(map, x + 1, y)) { //下
- return true;
- } else if (findWay(map, x, y + 1)) { //右
- return true;
- } else if (findWay(map, x - 1, y)) { //上
- return true;
- } else if (findWay(map, x, y - 1)) { //左
- return true;
- } else {
- map[x][y] = 3;
- return false;
- }
- } else { //map[x][y] = 1, 2, 3
- return false;
- }
- }
- }
- }
-
-
- ====== 迷宫地图 ======
- 1 1 1 1 1 1 1
- 1 0 0 0 0 0 1
- 1 0 0 0 0 0 1
- 1 1 1 0 0 0 1
- 1 0 0 0 0 0 1
- 1 0 0 0 0 0 1
- 1 0 0 0 0 0 1
- 1 1 1 1 1 1 1
- ====== 找路情况如下 ======
- 1 1 1 1 1 1 1
- 1 2 0 0 0 0 1
- 1 2 2 2 0 0 1
- 1 1 1 2 0 0 1
- 1 0 0 2 0 0 1
- 1 0 0 2 0 0 1
- 1 0 0 2 2 2 1
- 1 1 1 1 1 1 1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。