1个古典问题
古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
首先, 由于兔子是成对出现的, 我们在程序只需要考虑兔子是多少对, 而不是多少只。
其实, 对于这种数列求f(n)的问题, 我们的做法是先列出头几个n的值, 然后从中找规律
月份 | 兔子对数 | 分析 |
---|---|---|
1 | 1 | 1 + 0 |
2 | 1 | 1 + 0 |
3 | 2 | 1 + 1 |
4 | 3 | 2 + 1 |
5 | 5 | 3 + 2 |
6 | 8 | 5 + 3 |
7 | 13 | 8 + 5 |
8 | 21 | 13 + 8 |
如上图, 我们下面做看分析
假设f(n) 就是根据月份得出兔子对数的函数
f(1) = f(2) = 1; 是肯定的
当n >= 3 时
我们可以把f(n) 拆分
f(n) = 上个月份的兔子数 + 加上个月份新增的兔子数
其中 上个月份的兔子数 就是 f(n-1)
也就是 f(n) = f(n-1)
问题来了, 上个月份新增的兔子数是什么呢。
我们调用1个具体例子1个例子, 假设g(n) 是第n个月 下个月 新增的兔子数
那么 f(8) = f(7) + g(7) = 13 +8
也就是说g(7) = 8 , 而 f(7) = g(7) + 5 = f(6) + g(6) = 8 + 5
可以看出g(7) = f(6)
也就是讲 g(n) = f(n-1)
可以推导出f(n) = f(n-1) + g(n-1) = f(n-1) + f(n-2)
当前项等于前两项之和, 这就是传说中 Fiboracchi 数列!
当我们推导出规律之后, 程序就很容易写出来了
public class FiboracciSeq {
public static void main(String... args){
RabbitCount rb = new RabbitCount();
List<Integer> rabbitCountList = Arrays.asList(rb.f(1), rb.f(2),rb.f(3),rb.f(4),rb.f(5),rb.f(6));
rabbitCountList.forEach(System.out::println);
}
}
/**
* 古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
* 分析 https://mp.csdn.net/mp_blog/creation/success/127217870
*/
class RabbitCount{
/**
*
* @param n 月份
* @return 兔子数量
*/
public int f(int n){
if (n<3){
return 1;
}
return f(n-1) + g(n-1);
}
/**
*
* @param n
* @return n 下个月会新增的兔子数量
*/
public int g(int n){
if (n<3){
return 1;
}
return f(n-1);
}
}
输出:
1
1
2
3
5
8
Process finished with exit code 0