我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛
一道经典的算法题:
有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子。若兔子都不死,问第n (n为正整数) 个月的兔子对数为多少?
先来推导一下它的规律:
| 月 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| 可生育兔子对数 | 0 | 0 | 1 | 1 | 2 | 3 | 5 | 8 |
| 兔子总对数 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |
有没有发现可生育兔子对数在三月之后会和两月前兔子总对数对齐。原因很简单,即兔子三月后每月都会生小兔子。
且三月后,总兔子 = 上月兔子 + 当月可生育兔子,
当月可生育兔子 = 两月前兔子,
总兔子 = 上月兔子 + 两月前兔子。
假设月份为n,n>0
n≤2,F(n) = 1
n>2,F(n) = F(n-1) + F(n-2)
数列从第3项开始,每一项都等于前两项之和。这就是斐波那契数列 (Fibonacci sequence)。
代码实现:
用递归其实是非常直观的,只需要算出最后需要多少F(1) + F(2) 就行了,
比如F(5),
F(5) = F(4) + F(3)
= [F(3) + F(2)] + [F(2) + F(1)]
= {[F(2) + F(1)] + F(2)} + [F(2) + F(1)]
public static int sum(int n) {
if (n < 1)
return 0;
if (n < 3)
return 1;
return sum(n - 1) + sum(n - 2);
}
递归算法虽然写起来简单易懂,但是随着月份增长,调用次数也大幅度增加,浪费内存空间、效率较低。
那么这时可以对其做一点改变,从逆向运算改为正向。从前面的推论可以发现,整个兔子繁殖过程可以简化为涉及三个变量,即F(n)、F(n-1)、F(n-2) ,在代码中也可以用三个变量存储兔子对数值,并在计算出当月兔子后,将月份里的兔子对数往后移,并赋给空闲的两个变量。
public static int sum(int n) {
if(n < 1)
return 0;
if(n < 3)
return 1;
int f1 = 1; //上上月兔
int f2 = 1; //上月兔
int f3 = 2;
for(int i = 3; i < n; i++) {
f1 = f2;
f2 = f3;
f3 = f1 + f2; //当月兔
}
return f3;
}
最后用我贫瘠的前端知识发了一个码上掘金代码块。
斐波那契数列在计算机科学、数学和生物学等领域有着广泛的应用。在计算机科学中,斐波那契数列被用来实现高效的算法,例如求解最长公共子序列问题。在数学中,斐波那契数列可以用来表示数列的渐进复杂度,也可以用来解决递推问题。在生物学中,斐波那契数列可以用来模拟生物繁殖的过程。
总的来说,斐波那契数列是一种有趣且有用的数学模型,在许多领域都有着广泛的应用。
如果能给我一对这样的兔子就好了,到时候可以卖出好多兔子
祝大家兔年财源滚滚,money就像兔子生兔子一样