先贴上网上对此问题的主流描述:
有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
然后是网上对此问题的标准解法:
public class Demo01 {
public static void main(String args[]) {
for (int i = 1; i <= 20; i++)
System.out.println(f(i));
}
public static int f(int x) {
if (x == 1||x == 2)
return 1;
else
return f(x - 1) + f(x - 2);
}
}
先不说题目描述的有多简陋,多么令人无法忍受,这种解法看起来似乎没什么问题,甚至还有点高大上的感觉,但是让我们冷静下来好好想想他们是如何得出这个解题思路的?
首先,得拿起你的纸笔演算出有限数量的变化规律,也就是
程序分析:
第一个月-----------------1
第二个月-----------------1
第三个月-----------------2
第四个月-----------------3
第五个月-----------------5
第六个月-----------------8
第七个月-----------------13
然后通过你的细心观察,终于发现,除前两个月外,每个月的兔子数都是前两个月的兔子数之和,如何你再有点想象力,假设有个第0月,兔子数是0,那么除第一个月外每个月的兔子数量都是前两个月的兔子数量之和,所以得到了一个规律:
斐波那契数列, Sn = Sn-1+Sn-2
但是即使这样我们依然很难理解为什么思路会是这样子的!
原因很简单,因为题目本身就漏洞百出!
所以我建议,不!是要求将题目改成这样:
有一对兔子,在出生后的第2个月成熟,然后从出生后的第3个月起每个月都生一对小兔子,新出生的小兔子同样在出生后的第2个月成熟,然后从第三个月起每个月又生一对小兔子,假如所有兔子都不死,问每个月的兔子总数是多少?
这样问题就和思路对上了,但是还有问题!
这个问题就是如果你不先用纸笔去找到这个规律,你就没法写出这个程序!
对于这个情况我表示,这是一道给数学老师出的题吗?不先用纸笔去找规律就写不出来的程序我表示无限呵呵,所以我给出了我的解题方法,一种真正适合程序员,不需要动笔只需动脑即可的方案:
//程序员正确的解题思路
public static void myRecommend(){
int datuzi = 0;
//这是一个由每个月存在多少小兔子组成的数组
int[] xiaotuzis = new int[20];
xiaotuzis[0] = 1;
int month = 0;
while(month<20){
//判断本月是否有大兔子,有多少对大兔子就会出生多少对小兔子
if(datuzi>0){
xiaotuzis[month] += datuzi;
}
//判断本月的前一个月是否有小兔子,如果有就将上个月出生的小兔子全部变成大兔子
if(month>=1 && xiaotuzis[month-1]>0){
datuzi+=xiaotuzis[month-1];
xiaotuzis[month-1] = 0;
}
//计算本月小兔子总数
int sum = 0;
for(int i = 0;i<=month;i++){
sum+=xiaotuzis[i];
}
//打印本月兔子总数
System.out.println(sum+datuzi);
month ++;
}
}
我强烈认为,这样一种逻辑清晰,只要按照正确的逻辑,即使不知道其中隐藏的规律也照样能得出正确结论的方案才是我们程序员应该推崇的方案,至于那些只适合交给数学老师们研究的方案,建议大家就不要浪费时间了!