被一窩兔子絆倒!
古典問題:有一對兔子,從出生后第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個“,” .
即可得出:效率 遞歸算法 弱與 迭代算法,也就是說,本次運算中 遞歸算法 優於 迭代算法。