一、問題描述
- 一對兔子,從第3個月開始,每個月生1對小兔崽子,且每隻兔子都不會死亡;
- 小兔崽子也會按照上面的過程進行生小兔崽子
- 問第N月後,有幾對兔子
二、問題分析
月份 | 兔子數量(對) | 說明 |
---|---|---|
1月 | 1 | 第1月,①兔子不能生 |
2月 | 1 | 第2月,①兔子不能生 |
3月 | 2 | 第3月,①兔子滿3月,生1對兔子② |
4月 | 3 | 第4月,①兔子生1對兔子③,②兔子不能生 |
5月 | 5 | 第5月,①兔子生1對兔子④,②③兔子不能生 |
6月 | 8 | 第6月,①兔子生1對兔子⑤,②兔子生1對兔子⑥,③兔子不能生 |
從上面的分析來看,從第三個月開始,每個月的兔子數量都是前兩個月的和 1
可推導出公式:sum(n) = sum(n - 1) + sum(n - 2), n > 2
三、代碼實現
- 遞歸算法
/**
* 計算兔子數量 (遞歸算法)
*
* @param month 月份
* @return
* @throws Exception
*/
private static int rabbit(int month) throws Exception {
if (month <= 0) {
// 不大於0的月份沒有意義
throw new Exception("月份必須大於0");
}
if (month <= 2) {
// 第1、2個月,兔子只有1對
return 1;
}
// 第3個月開始,兔子有前1月 + 前2月的兔子數量
return rabbit(month - 1) + rabbit(month - 2);
}
- 循環算法
/**
* 計算兔子數量 (循環算法)
*
* @param month 月份
* @return
* @throws Exception
*/
private static int rabbit2(int month) throws Exception {
int[] nums = new int[month];
if (month <= 0) {
// 不大於0的月份沒有意義
throw new Exception("月份必須大於0");
}
for (int i = 0; i < month; i++) {
if (i < 2) {
// 第1、2個月,兔子只有1對
nums[i] = 1;
} else {
// 第3個月開始,兔子有前1月 + 前2月的兔子數量
nums[i] = nums[i - 1] + nums[i - 2];
}
}
// 返回最後一個月份的兔子數量
return nums[month - 1];
}
- 在main方法中調用
public static void main(String[] args) {
Scanner key = new Scanner(System.in);
System.out.println("請輸入一個整數表示月份:");
int month = key.nextInt();
try {
System.out.println("遞歸算法:" + month + "月後,共有" + rabbit(month) + "對兔子");
System.out.println("循環算法:" + month + "月後,共有" + rabbit2(month) + "對兔子");
} catch (Exception e) {
e.printStackTrace();
}
key.close();
}
四、代碼運行結果
一個很經典的算法題,分享給大家。根據上面的分析,可以看出來這是一個斐波那契數列問題,只要找出來規律,然後按照這個規律編碼實現就好了。
↩︎