兔群繁殖之谜
摘要
这个问题是一个经典的斐波那契数列问题。研究的是一种特殊兔子的繁殖模式,每对成年兔子每个月会生育一对新的小兔子。新生的小兔子需要一个月成长,到第二个月才能开始繁殖。我们从一对新生的小兔子开始,目标是计算在第 个月末,总共有多少对兔子。
问题描述
生物学家小 R 正在研究一种兔子品种的繁殖模式,其规律如下:
- 每对成年兔子每个月会生育一对新的小兔子(一雌一雄)。
- 新生的小兔子需要一个月成长,到第二个月才能开始繁殖。
- 兔子不会死亡。
给定一个整数 (1 ≤ ≤ 50),表示月份数,要求计算第 个月末兔子的总对数。
测试样例
- 输入: → 返回: 1
- 输入: → 返回: 8
- 输入: → 返回: 987
解题思路
这是一个经典的斐波那契数列问题。每个月的兔子总对数满足以下递推关系:
其中 表示第 个月的兔子总对数。
- 初始条件:
- 第 个月:
- 第 个月:
从第 个月开始,兔子群体按照上述递推公式增长。
代码实现
我们可以采用递归的记忆化搜索方式和迭代方式两种解法。
Go 语言实现
递归 + 记忆化搜索
package main
import "fmt"
// 初始化dp数组
var dp = [51]int{}
// 计算第A个月末兔子的总对数
func solution(A int) int {
// 初始化基本情况
dp[0], dp[1] = 1, 1
return fib(A)
}
// 使用递归和记忆化搜索来计算斐波那契数
func fib(a int) int {
// 如果已经计算过,直接返回结果
if dp[a] != 0 {
return dp[a]
}
// 递归计算并保存结果
dp[a] = fib(a-1) + fib(a-2)
return dp[a]
}
func main() {
// 测试用例
fmt.Println(solution(1)) // 输出:1
fmt.Println(solution(5)) // 输出:8
fmt.Println(solution(15)) // 输出:987
}
迭代版
package main
import "fmt"
// 计算第A个月末兔子的总对数(迭代版)
func solution(A int) int {
if A == 0 || A == 1 {
return 1
}
// 初始化前两个斐波那契数
prev1, prev2 := 1, 1
var current int
// 迭代计算斐波那契数列
for i := 2; i <= A; i++ {
current = prev1 + prev2
prev1 = prev2
prev2 = current
}
return current
}
func main() {
// 测试用例
fmt.Println(solution(1)) // 输出:1
fmt.Println(solution(5)) // 输出:8
fmt.Println(solution(15)) // 输出:987
}
Python 版本实现
迭代版
def solution(A: int) -> int:
"""
计算第 A 个月末兔子的总对数(使用迭代版本)。
:param A: 第 A 个月
:return: 该月末兔子的总对数
"""
# 如果是第一个或第二个月,兔子的数量是 1
if A == 0 or A == 1:
return 1
# 初始化前两个斐波那契数
prev1, prev2 = 1, 1
current = 0
# 迭代计算斐波那契数列
for i in range(2, A + 1):
current = prev1 + prev2
prev1 = prev2
prev2 = current
return current
if __name__ == "__main__":
# 测试用例
print(solution(1) == 1) # True
print(solution(5) == 8) # True
print(solution(15) == 987) # True
复杂度分析
- 时间复杂度: ,因为每一个月份的兔子数量只会计算一次。
- 空间复杂度: 递归方式需要 的空间来存储已计算的斐波那契数。迭代版本的空间复杂度为 ,因为仅用常量空间记录前两个状态。
总结
这个问题是经典的斐波那契问题的一个变体。通过动态规划(记忆化递归和迭代)的方式,可以有效地计算兔子繁殖的总对数。迭代方式在空间利用上更为高效,是推荐的解法。