关于“古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子……” 理清问题,无往而不胜
被一窝兔子绊倒!
古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
本人是在搜问题时,发现有伙伴在百度提问,并试着理解并寻找问题发生的根源 —— 误解了题目,还是解题困难。通过接受和理解问题提出者的困惑后,发现疑惑和误解是可以理解的,我试着为题目增加一些限制和说明,使得对题目的把握更加准确,或者说减少题目本身存在的歧义,使之更加明确。至于问题的解法,方法有多种,而且提供解法的文章数不胜数,不再赘述,如需了解,请再简单搜索一下。
(百度问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子.如果您看到这两处的说法一样,不要奇怪,都出自于本人。其中内容包括问题的直接回答,及对其中一个回答者的内容进行评论,即回答了其中一个回答者的回复)
题干分析(减少歧义):不可将 “第3个月”看成了(理解成)“隔3个月”。准确的理解是“如 当下是1月初,2月初则是第二月,3月初就是第三个月”。这里如果说成两月即61天(2个月,忽略闰二月,假如闰二月时,按月算)后。这样会减少不是歧义。
问题解析:这是一个典型的“波非那切数列”:前面相邻两项之和,构成了后一项(即:后一项,总等于前两项之和)。
关于:“前面相邻两项之和,构成了后一项”的理解:(
依据:“第3个月起每个月都生一对”(这里容易造成误解的是,第3个月起,这个起始时间点,是指月初还是月末的问题,从这个经典问题的初衷来说,是指的月初)。
因此:“第3个月,即隔2个月(约61天,闰月则忽略并按月来算)就发生”。
结论:
(1) 上一个月的兔子(n),在下一个月,保持到下一月(n);即 老兔数 = 上月兔子总数。
(2) 第3月出生的兔仔,由上上月(第 前3月)的兔子所生,且是1对 生 1对,1:1的比例。及 兔仔数 = 上上月的兔子总数。
(3) 总数 = 上月兔子总数 + 上上月的兔子总数(也即 相邻两项之和)
个人的一段小解法:
(1)迭代算法方式
1 package com.activitiserver; 2 3 public class server { 4 5 // 1 1 2 3 5 6 public static void main(String[] args) { 7 int month; 8 for (int i = 1;i<10;i++){ 9 month = i; 10 int count = printCountByMonth(month); 11 System.out.println("第" + month + "月,小兔数为:" + count +"(对)"); 12 System.out.println(); 13 } 14 } 15 16 public static int printCountByMonth(int month){ 17 if (month < 1) throw new RuntimeException("月数不可小于1个月"); 18 int first = 1; 19 int second = 1; 20 int third = 0; 21 if (month == 1 || month == 2) return 1; 22 boolean flag = true; 23 while (month > 0){ 24 first = second; 25 second = third; 26 third = first + second; 27 month --; 28 if (flag){ 29 flag = false; 30 }else{ 31 System.out.print(","); 32 } 33 System.out.print(third); 34 } 35 System.out.println(); 36 return third; 37 } 38 }
运行结果:
第1月,小兔数为:1(对) 第2月,小兔数为:1(对) 1,1,2 第3月,小兔数为:2(对) 1,1,2,3 第4月,小兔数为:3(对) 1,1,2,3,5 第5月,小兔数为:5(对) 1,1,2,3,5,8 第6月,小兔数为:8(对) 1,1,2,3,5,8,13 第7月,小兔数为:13(对) 1,1,2,3,5,8,13,21 第8月,小兔数为:21(对) 1,1,2,3,5,8,13,21,34 第9月,小兔数为:34(对) Process finished with exit code 0
(2)递归算法方式
1 public class BFNQFun { 2 public static void main(String[] args) { 3 int in = 9; 4 int count = getCount(in); 5 System.out.println(); 6 System.out.println("in = " + in+ ",getCount = " + count); 7 } 8 9 public static int getCount(int in){ 10 System.out.print(in + ","); 11 if (in <= 0) return 1; 12 if (in == 1) return 1; 13 return getCount(in - 1) + getCount(in - 2); 14 } 15 }
运行结果:(为了便于阅读,对下面的换行是手动修改的,并非原样,但数据总数不变)
9,8,7,6,5,4,3,2,1,0,1,2,1,0,3,2,1,0,1,4,3,2,1,0,1,2,1,0, 5,4,3,2,1,0,1,2,1,0,3,2,1,0,1,6,5,4,3,2,1,0,1,2,1,0,3,2, 1,0,1,4,3,2,1,0,1,2,1,0,7,6,5,4,3,2,1,0,1,2,1,0,3,2,1,0, 1,4,3,2,1,0,1,2,1,0,5,4,3,2,1,0,1,2,1,0,3,2,1,0,1, in = 9,getCount = 55
小结:
从打印的“,”符号统计:
迭代算法:35个“,” .
递归算法:108个“,” .
即可得出:效率 递归算法 弱与 迭代算法,也就是说,本次运算中 递归算法 优于 迭代算法。