10、统计每个月兔子的总数
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。
例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。
一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?
数据范围:输入满足 1≤n≤31
输入描述:
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数
思路一
1.根据表可发现,当前月数=前一个月+前前一个月 如:3月只数=2月只数+1月只数
2.利用if和for循环累计复制。计算出第X月兔子数
难点: 对于如何将上个月和上上个月值进行累加到当月。
解决:用交换赋值法 如:
count = m1 + m2;//3月份时候3月=1+2
m1 = m2;//将2月份赋值给一月份
m2 = count;//将3月份复制给2月份 若是4月=3+2
| 月数 | 只数 |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 3 |
| 5 | 5 |
具体实现
#include<stdio.h>
int main()
{
int n = 31, m1 = 1,m2=1, count = 0;//n代表月数 count 代表兔子总数,m1和m2分别代表第一个月和第二个月
printf("输入月份数:");
scanf_s("%d", &n);
if (n == 1 || n == 2) {
printf("第%d个月共有%d 只兔子。\n",n, m1);
}
else if (n <=31) {
for (int i = 3; i <= n; i++) {
count = m1 + m2;//3月份时候3月=1+2
m1 = m2;//将2月份赋值给一月份
m2 = count;//将3月份复制给2月份 若是4月=3+2
}
printf("第 %d个月共有%d 只兔子。\n", n, count);
}
else {
printf("输入超出月数\n");
return 0;
}
return 0;
}
运行结果
输入月份数:6
第 6个月共有8 只兔子。
复杂度
时间:O(n)————n为输入的月数,代码中运行次数最多的就是if(n<=30)下的循环语句.
空间:O(1)——没有用到存储,所以空间复杂度为常数
思路二
思路参考大神的,详情:蓝蓝计算机考研算法-day07统计每个月兔子总数 - 掘金 (juejin.cn)
递归公式** f(n)=f(n−1)+f(n−2)f(n)=f(n−1)+f(n−2)**,其实就是斐波那契数列,然后利用此公式逐层递归即可。
具体实现
#include <stdio.h>
int f(int n) {//递归方法
if (n <= 2) {//n为月数
return 1;
}
else {
return f(n - 1) + f(n - 2);//本月数=前两个月数目相加
}
}
int main() {
int n;
printf("请输入月份:");
scanf_s("%d", &n);
printf("第%d个月的兔子总数为:%d\n", n, f(n));
return 0;
}
运行结果
- 时间复杂度 O(2^n) --- 遍历整个二叉树(节点数)n可理解为二叉树的层数
- 空间复杂度 O(n) --- 递归栈的深度为 n
小结
找到思路,无法用代码将其表示出来,很基本的逻辑还没有熟练掌握。需要多加练习。
今天犯错误将 printf()的输出里面的变量加上了&取地址,导致查找了很久,用最简单的尝试方法最终还是发现了这个错误。