Day07 2023/01/14
难度:简单
题目
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?
数据范围:1 ≤ n ≤ 31
输入描述:
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数
示例
输入:5
输出:5
思路一
| 月份 | 兔子数 |
|---|---|
| 第1个月 | 1只兔子 |
| 第2个月 | 1只兔子 |
| 第3个月 | 2只兔子 |
| 第4个月 | 3只兔子 |
| 第5个月 | 5只兔子 |
可以发现除了前两个月有些特殊外,剩下的月份的兔子数都是它前两个月兔子数之和。因此可得递归公式 ,其实就是斐波那契数列,然后利用此公式逐层递归即可。 如图所示:
思路二
-
使用 迭代 的方式,分别设置三种兔子的数量,三个月及其以上的(可生育
k3),两个月的和一个月的(不可生育k2和k1),每过一个月就更新一次,最后返回三种兔子数量之和。 -
其中更新细节为,每过一个月
k3 = k3 + k2; k2 = k1; k1 =k3;
关键点
- 迭代的方式中,注意前两个月比较特殊,更新方式单独处理。
算法实现
c++代码实现1-递归
#include <iostream>
using namespace std;
// 计算n月时的兔子数
int CalNum (int n) { //n为月数
if(n == 1 || n == 2) return 1; //当n为1或者2的时候跳出递归
return CalNum(n - 1) +CalNum(n-2); //本月的兔子数等于前两个月兔子数相加(本质是斐波那契数列)
}
//方法一:递归(斐波那契)
int main () {
int n = 0;
cout << "请输入月份: ";
cin >> n;
cout << "第" << n << "个月兔子数为:" << CalNum(n) << endl;
return 0;
}
- 时间复杂度 --- 遍历整个二叉树(节点数)
- 空间复杂度 --- 递归栈的深度为 n
c++代码实现2-迭代
// 计算n月时的兔子数
int CalNum (int n) { //n为月数
int k1 = 0, k2 = 0, k3 = 0; //k1为年龄一个月的兔子,k2为年龄两个月的兔子, k3为年龄三个月的兔子。
//前两个月比较特殊,先初始化到第二个月的状态
k1 = 0;
k2 = 1;
k3 = 0;
for (int i = 3; i <=n; i++) {
k3 += k2;
k2 = k1;
k1 = k3;
}
return k1 + k2 + k3;
}
// 方法二:迭代
int main () {
int n = 0;
cout << "请输入月份: ";
cin >> n;
cout << "第" << n << "个月兔子数为:" << CalNum(n) << endl;
return 0;
}
- 时间复杂度 --- 循环n-2次,n为月份数
- 空间复杂度 ---常数级空间
总结
- 了解递归,迭代这些基本的算法思想,并学会处理一些特殊的情况。