当前位置:   article > 正文

回溯算法(递归)_int test(int x){return (x==1)?1:(x+test(x-1))}

int test(int x){return (x==1)?1:(x+test(x-1))}
递归:递归就是在函数里调用函数本身。

基线条件和递归条件
1、基线条件:就是指结束调用的条件,避免形成无限循环。
2、递归条件:就是指函数调用自己的条件。
3、递归必须向基线条件逼近,否则就会出现无线递归。

一、打印问题

给出一个整数,使用递归打印它。

  1. public class Recursion {
  2. public static void main(String[] args) {
  3. Recursion.test(4);
  4. }
  5. public static void test(int a) {
  6. if (a > 2) {
  7. test(a-1);
  8. }
  9. System.out.println(a);
  10. }
  11. }
  12. 解读:
  13. 第一次调用test,创建一个栈,传入4,判断4是否会大于24大于2进行第二次调用,4-1
  14. 第二次调用test,创建一个栈,传入3,判断3是否会小于23大于2进行第三次调用,3-1
  15. 第三从调用test,创建一个栈,传入2,判断2是否会大于22等于2进行返回
  16. 第一次返回,销毁栈,打印2
  17. 第二次返回,销毁栈,打印3
  18. 第三次返回,销毁栈,打印4
  19. 结束程序
  20. 2
  21. 3
  22. 4

二、累加问题

给出一个整数,使用递归求出它累加的和。

  1. public class Accumulation {
  2. public static void main(String[] args) {
  3. int a = Accumulation.test(3);
  4. System.out.println(a);
  5. }
  6. public static int test(int x) {
  7. if (x == 1) {
  8. return 1;
  9. } else {
  10. return x+test(x-1);
  11. }
  12. }
  13. }
  14. 解读:
  15. 1.在main中第一次调用test,创建第一层栈,传入3,判断是否等于13大于1,符合递归条件,进行第二次调用test,3-1
  16. 2.第二次调用test,创建第二层栈,传入2,判断是否等于12大于1,符合递归条件,进行第三次调用test,2-1
  17. 3.第三次调用test,创建第三层栈,传入1,判断是否等于11等于1,符合基线条件,进行返回
  18. 4.第三层栈,返回1
  19. 5.第二层栈,返回32+1
  20. 6.第一层栈,返回63+2+1
  21. 程序结束
  22. 6

三、阶层问题
给出一个整数,使用递归求出它的阶乘。

  1. public class Factorial {
  2. public static void main(String[] args) {
  3. int a = Factorial.test(5);
  4. System.out.println(a);
  5. }
  6. public static int test(int x){
  7. if (x == 1){ // 基线条件
  8. return 1;
  9. }else{ // 递归条件
  10. return test(x-1) * x;
  11. }
  12. }
  13. }
  14. 递归解读:
  15. 1. 在main中第一次调用test,创建第一层栈,传入5,判断是否等于15大于1,符合递归条件,进行第二次调用test5-1
  16. 2. 第二次调用test,创建第二层栈,传入4,判断是否等于14大于1,符合递归条件,进行第三次调用test4-1
  17. 3. 第三次调用test,创建第三层栈,传入3,判断是否等于13大于1,符合递归条件,进行第四次调用test3-1
  18. 4. 第四次调用test,创建第四层栈,传入2,判断是否等于12大于1,符合递归条件,进行第五次调用test2-1
  19. 5. 第五次调用test,创建第五层栈,传入1,判断是否等于11等于1,符合基线条件,进行返回
  20. 6. 第五层栈,销毁栈,返回1return 1;
  21. 7. 第四层栈,销毁栈,返回2return test(2-1) * 2;
  22. 8. 第三层栈,销毁栈,返回6return test(3-1) * 3;
  23. 9. 第二层栈,销毁栈,返回24return test(4-1) * 4;
  24. 10. 第一层栈,销毁栈,返回120return test(24-1) * 5;
  25. 11. 程序结束
  26. 120

四、斐波那契
用递归求出斐波那契数1,1,2,3,4,5,8,13...给一个整数x,求出它的值是多少。

  1. public class Fibonacci {
  2. public static void main(String[] args) {
  3. int x = 4;
  4. int a = Fibonacci.test(x);
  5. if (a != -1){
  6. System.out.println("当x="+x+",对应的斐波那契是"+a);
  7. }
  8. }
  9. //思路分析:斐波那契是前两个数之和,且必须是整数。
  10. public static int test(int x) {
  11. if (x >= 1) { //斐波那契必须是整数
  12. if (x == 1 || x == 2) { //
  13. return 1;
  14. } else {
  15. return test(x - 1) + test(x - 2);
  16. }
  17. } else {
  18. System.out.println("要求输入的x必须是大于等于1的整数");
  19. return -1;
  20. }
  21. }
  22. }
  23. 解读:
  24. 第一次调用test方法,向方法传递整数x(x=4
  25. 判断x是否大于等于1(因为斐波那契数不能小于1),小于1,输出提示信息,并返回-1
  26. 大于等于1,则在判断x是否是12,是12则返回1;(因为12的斐波那契数是1
  27. 否则进行第二次第一个调用test,创建栈,传入3 + 第二次第二个调用test,创建栈,传入2
  28. 第二次第一个test,进行x是否大于等于1的判断,3>=1,在判断是否会等于123不等于12
  29. 进行第三次第一个调用test,创建栈,传入2+ 第三次第二个调用test,创建栈,传入1
  30. 第三次第一个test,进行x是否大于等于1的判断,2>=1,在判断是否会等于122等于12,进行返回
  31. 第三次第二个test,进行x是否大于等于1的判断,1>=1,在判断是否会等于121等于12,进行返回
  32. 第二次第二个test,进行x是否大于等于1的判断,2>=1,在判断是否会等于122等于12,进行返回
  33. 第三次第一个test,返回,1
  34. 第三次第二个test,返回1
  35. 第二次第一个test,返回2
  36. 第二次第二个test,返回1
  37. 第一次返回调用处,返回3
  38. 3

 


五、猴子吃桃问题
有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个。以后的每天猴子都吃其中的一半,然后再多吃一个。
当第10天时,想再吃时(还没有吃),发现只有一个桃子了。问最初有多少个桃子。
 

  1. public class MonkeyPeach {
  2. public static void main(String[] args) {
  3. int day = 1;
  4. int a = MonkeyPeach.test(day);
  5. if (a != -1) {
  6. System.out.println("第" + day + "天有" + a + "个桃");
  7. }
  8. }
  9. public static int test(int day) {
  10. if (day == 10) { // 第十天只有1个桃
  11. return 1;
  12. } else if (day >= 1 && day <= 9) { //天数必须在1-10天之内
  13. return (test(day + 1) + 1) * 2;
  14. } else {
  15. System.out.println("day必须在1-10之间");
  16. return -1;
  17. }
  18. }
  19. }
  20. 思路分析:逆推
  21. 1. day10 有 1个桃子
  22. 2. day9  有 (day10+1)*2=4 个桃子  4/2-1=1
  23. 3. day8  有 (day9+1)*2=10 个桃子  10/2-1=4
  24. 规律就是 前一天的桃子 = (后一天的桃子 +1)*2
  25. 输入天数可以获取当天桃子的个数,输入6
  26. 第一次调用test(6),创建栈,出传入6,判断是否等于106不等于10,在判断是否大于等于1且小于等于96大于等于1且小于等于9,进行第二次调用test
  27. 第二次调用test(6+1),创建栈,传入7,判断是否等于107不等于10,在判断是否大于等于1且小于等于97大于等于1且小于等于9,进行第三次调用test
  28. 第三次调用test(7+1),创建栈,传入8,判断是否等于108不等于10,在判断是否大于等于1且小于等于98大于等于1且小于等于9,进行第四次调用test
  29. 第四次调用test(8+1),创建栈,传入9,判断是否等于109不等于10,在判断是否大于等于1且小于等于99大于等于1且小于等于9,进行第五次调用test
  30. 第五次调用test(9+1),创建栈,传入10,判断是否等于1010等于10,进行返回,返回1
  31. 第五次调用,return 1,返回1,销毁栈
  32. 第四次调用,return (1 + 1) * 2,返回4,销毁栈
  33. 第五次调用,return (4 + 1) * 2,返回10,销毁栈
  34. 第五次调用,return (10 + 1) * 2,返回22,销毁栈
  35. 第五次调用,return (22 + 1) * 2,返回46,销毁栈
  36. 程序结束
  37. 46

六、汉诺塔问题
把圆盘从a塔移动到c塔,且小于圆盘要在上面。

  1. public class HanoiTower {
  2. public static void main(String[] args) {
  3. Test test = new Test();
  4. test.move(5,'A', 'B', 'C');
  5. }
  6. }
  7. class Test{
  8. // num 表示要移动的个数,a,b,c 分别表示A塔 B塔 C塔
  9. public static void move(int num, char a, char b, char c){
  10. // 如果只有一个圆盘
  11. if (num == 1){
  12. System.out.println(a + "->" + c);
  13. }else{
  14. // 如果有多个圆盘,可以看成两个,最下面的和上面的所有圆盘(num-1)
  15. //(1)先移动上面所有的圆盘到b,借助c
  16. move(num-1, a, c, b);
  17. //(2)把最下面的这个圆盘,移动到c
  18. System.out.println(a + "->" + c);
  19. //(3)再把b塔的所有圆盘,移动到c,借助a
  20. move(num-1, b, a, c);
  21. }
  22. }
  23. }
  24. 汉诺塔解读:
  25. main创建第一层栈,第一次调用move,创建第二层栈,传入 3,A,B,C,判断3是否等于13不等于1
  26. 则进行第二次调用move,创建第三层栈,传入 2,A,C,B,判断2是否等于12不等于1
  27. 则进行第三次调用move,创建第四层栈,传入 1,A,B,C,判断1是否等于11等于1,输出 A->C,销毁栈,返回第三层
  28. 第三层栈,输出 A->B,
  29. 第四次调用move,创建第四层栈,传入1,C,A,B,判断1是否等于11等于1,输出 C->B,销毁栈,返回第三层
  30. 销毁栈,返回到第二层
  31. 第二层栈,输出 A->C,
  32. 第二层栈,进行第五次调用move,创建第三层栈,传入2,B,A,C,判断2是否等于12不等于1
  33. 则进行第六次调用move,创建第四层栈,传入 1,B,C,A,判断1是否等于11等于1,输出 B->A,销毁栈,返回第三层
  34. 第三层栈,输出B->C
  35. 第三层,进行第七次调用move,创建第四层栈,传入1,C,B,A,判断1是否等于11等于1,输出 A->C,销毁栈,返回第三层
  36. 销毁栈,返回第二层
  37. 销毁栈,返回第一层调用处
  38. 结束程序
  39. A->C
  40. A->B
  41. C->B
  42. A->C
  43. B->A
  44. B->A
  45. C->A

 ▲表示输出

 

七、老鼠出迷宫问题

  1. public class Maze {
  2. public static void main(String[] args) {
  3. //创建迷宫,用二维数组表示 int[][] map = new int[8][7]
  4. //先规定 map数组的元素值:0表示可以走,1表示障碍物
  5. int[][] map = new int[8][7];
  6. // 设置障碍物
  7. //将最上面的一行和最下面的一行,全部设置为1
  8. for (int i = 0; i < 7; i++) {
  9. map[0][i] = 1;
  10. map[7][i] = 1;
  11. }
  12. //将最左面的一列和最右面的一列,全部设置为1
  13. for (int i = 0; i < 8; i++) {
  14. map[i][0] = 1;
  15. map[i][6] = 1;
  16. }
  17. map[3][1] = 1;
  18. map[3][2] = 1;
  19. // 输出地图
  20. System.out.println("====== 迷宫地图 ======");
  21. for (int i = 0; i < map.length; i++) {
  22. for (int j = 0; j < map[i].length; j++) {
  23. System.out.print(map[i][j] + " ");
  24. }
  25. System.out.println();
  26. }
  27. // 使用findWay给老鼠找路
  28. test t = new test();
  29. t.findWay(map,1,1);
  30. System.out.println("====== 找路情况如下 ======");
  31. for (int i = 0; i < map.length; i++) {
  32. for (int j = 0; j < map[i].length; j++) {
  33. System.out.print(map[i][j] + " ");
  34. }
  35. System.out.println();
  36. }
  37. }
  38. }
  39. // 使用递归回溯解决老鼠出迷宫
  40. // 1. findWay方法就是专门来找迷宫路径的
  41. // 2. 如果找到返回true,没有找到返回false
  42. // 3. map 就是二维数组,即表示迷宫
  43. // 4. x,y就是老鼠的坐标,初始化为 (1, 1)
  44. // 5. 因为是递归找路,所以先规定 map数组的各个值的含义
  45. // 0表示可以走,1表示障碍物,2表示可以走,3表示走过,但走不通是死路
  46. // 6. 当map[6][5]=2 就说明找到通路,就可以结束,否则就继续找。
  47. // 7. 先确定老鼠找路策略 下-> 右-> 上-> 左
  48. class test {
  49. public boolean findWay(int[][] map, int x, int y) {
  50. if (map[6][5] == 2) { //说明已经找到
  51. return true;
  52. } else {
  53. if (map[x][y] == 0) { //当前这个位置0,说明表示可以走
  54. // 我们可以假定走通
  55. map[x][y] = 2;
  56. // 使用找路策略,来确定该位置是否真的可以走通
  57. // 下-> 右-> 上-> 左
  58. if (findWay(map, x + 1, y)) { //下
  59. return true;
  60. } else if (findWay(map, x, y + 1)) { //右
  61. return true;
  62. } else if (findWay(map, x - 1, y)) { //上
  63. return true;
  64. } else if (findWay(map, x, y - 1)) { //左
  65. return true;
  66. } else {
  67. map[x][y] = 3;
  68. return false;
  69. }
  70. } else { //map[x][y] = 1, 2, 3
  71. return false;
  72. }
  73. }
  74. }
  75. }
  76. ====== 迷宫地图 ======
  77. 1 1 1 1 1 1 1
  78. 1 0 0 0 0 0 1
  79. 1 0 0 0 0 0 1
  80. 1 1 1 0 0 0 1
  81. 1 0 0 0 0 0 1
  82. 1 0 0 0 0 0 1
  83. 1 0 0 0 0 0 1
  84. 1 1 1 1 1 1 1
  85. ====== 找路情况如下 ======
  86. 1 1 1 1 1 1 1
  87. 1 2 0 0 0 0 1
  88. 1 2 2 2 0 0 1
  89. 1 1 1 2 0 0 1
  90. 1 0 0 2 0 0 1
  91. 1 0 0 2 0 0 1
  92. 1 0 0 2 2 2 1
  93. 1 1 1 1 1 1 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/590473
推荐阅读
相关标签
  

闽ICP备14008679号