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 {
public int f(int n) {
if (n < 1) {
throw new IllegalArgumentException(n + "不能小于 1");
}
if (n == 1 || n == 2) {
return n;
}
return f(n - 2) + f(n - 1);
}
}
<a name="WDwIW"></a>
# 5.3 循环迭代
- n = 1
- 一步
- f(1) = 1
- n = 2
- 一步一步
- 直接 2 步
- f(2) = 2
- n = 3
- 先到达 f(1),然后从 f(1) 直接跨 2 步
- 先到达 f(2),然后从 f(2) 跨 1 步
- one 保存最后走一步
- two 保存最后走两步
- f(3) = two + one
- f(3) = f(1) + f(2)
- two = f(1)
- one = f(2)
- n = 4
- 先到达 f(2),然后从 f(2) 直接跨 2 步
- 先到达 f(3),然后从 f(3) 跨 1 步
- f(4) = two + one
- f(4) = f(2) + f(3)
- two = f(2)
- one = f(3)
- ......
- n = x
- 先到达 f(x-2),然后从 f(x-2) 直接跨 2 步
- 先到达 f(x-1),然后从 f(x-1) 跨 1 步
- f(x) = two + one
- f(x) = f(x-2) + f(x-1)
- two = f(x-2)
- one = f(x-1)
```java
package s01.e05;
public class TestStep2 {
public int loop(int n) {
if (n < 1) {
throw new IllegalArgumentException(n + "不能小于 1");
}
if (n == 1 || n == 2) {
return n;
}
int one = 2; // 初始化为走到第二级台阶的走法
int two = 1; // 初始化为走到第一级台阶的走法
int sum = 0;
for (int i = 3; i < n; i++) {
// 最后跨 2 步 + 最后跨 1 步的走法
sum = two + one;
two = one;
one = sum;
}
return sum;
}
}
5.4 小结
- 方法调用自身称为递归,利用变量的原值推出新值称为迭代。
- 递归
- 优点:大问题转化为小问题,可以减少代码量,同时代码精简,可读性好
- 缺点:递归调用浪费了空间,而且递归太深容易造成堆栈的溢出
- 迭代
- 优点:代码运行效率好,因为时间只因循环次数增加而增加,而且没有额外的空间开销
- 缺点:代码不如递归简洁,可读性好