5.1 题目

有 n 步台阶,一次只能上 1 步或 2 步,共有多少种走法

5.2 递归

  • n = 1
    • 一步
    • f(1) = 1
  • n = 2
    • 一步一步
    • 直接 2 步
    • f(2) = 2
  • n = 3
    • 先到达 f(1),然后从 f(1) 直接跨 2 步
    • 先到达 f(2),然后从 f(2) 跨 1 步
    • f(3) = f(1) + f(2)
  • n = 4
    • 先到达 f(2),然后从 f(2) 直接跨 2 步
    • 先到达 f(3),然后从 f(3) 跨 1 步
    • f(4) = f(2) + f(3)
  • ……
  • n = x
    • 先到达 f(x-2),然后从 f(x-2) 直接跨 2 步
    • 先到达 f(x-1),然后从 f(x-1) 跨 1 步
    • f(x) = f(x-2) + f(x-1) ```java package s01.e05;

public class TestStep {

  1. public int f(int n) {
  2. if (n < 1) {
  3. throw new IllegalArgumentException(n + "不能小于 1");
  4. }
  5. if (n == 1 || n == 2) {
  6. return n;
  7. }
  8. return f(n - 2) + f(n - 1);
  9. }

}

  1. <a name="WDwIW"></a>
  2. # 5.3 循环迭代
  3. - n = 1
  4. - 一步
  5. - f(1) = 1
  6. - n = 2
  7. - 一步一步
  8. - 直接 2 步
  9. - f(2) = 2
  10. - n = 3
  11. - 先到达 f(1),然后从 f(1) 直接跨 2 步
  12. - 先到达 f(2),然后从 f(2) 跨 1 步
  13. - one 保存最后走一步
  14. - two 保存最后走两步
  15. - f(3) = two + one
  16. - f(3) = f(1) + f(2)
  17. - two = f(1)
  18. - one = f(2)
  19. - n = 4
  20. - 先到达 f(2),然后从 f(2) 直接跨 2 步
  21. - 先到达 f(3),然后从 f(3) 跨 1 步
  22. - f(4) = two + one
  23. - f(4) = f(2) + f(3)
  24. - two = f(2)
  25. - one = f(3)
  26. - ......
  27. - n = x
  28. - 先到达 f(x-2),然后从 f(x-2) 直接跨 2 步
  29. - 先到达 f(x-1),然后从 f(x-1) 跨 1 步
  30. - f(x) = two + one
  31. - f(x) = f(x-2) + f(x-1)
  32. - two = f(x-2)
  33. - one = f(x-1)
  34. ```java
  35. package s01.e05;
  36. public class TestStep2 {
  37. public int loop(int n) {
  38. if (n < 1) {
  39. throw new IllegalArgumentException(n + "不能小于 1");
  40. }
  41. if (n == 1 || n == 2) {
  42. return n;
  43. }
  44. int one = 2; // 初始化为走到第二级台阶的走法
  45. int two = 1; // 初始化为走到第一级台阶的走法
  46. int sum = 0;
  47. for (int i = 3; i < n; i++) {
  48. // 最后跨 2 步 + 最后跨 1 步的走法
  49. sum = two + one;
  50. two = one;
  51. one = sum;
  52. }
  53. return sum;
  54. }
  55. }

5.4 小结

  • 方法调用自身称为递归,利用变量的原值推出新值称为迭代。
  • 递归
    • 优点:大问题转化为小问题,可以减少代码量,同时代码精简,可读性好
    • 缺点:递归调用浪费了空间,而且递归太深容易造成堆栈的溢出
  • 迭代
    • 优点:代码运行效率好,因为时间只因循环次数增加而增加,而且没有额外的空间开销
    • 缺点:代码不如递归简洁,可读性好