Day7
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。
例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。
一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?
数据范围:输入满足 1≤�≤31 1≤n≤31
输入描述:
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数
示例1
输入:
3
复制
输出:
2
思路分析:
-
法1:经典的斐波那契数列,F(N) = F(N-1)+F(N-2),经典递归三部曲可以得出
相当于将每一层的和累计到上一层
- 法2:迭代法实现,这个思路更简单,我们可以直接利用迭代,逐个记录F(i-2)和F(i-1)和F(i)的值,然后循环累加
具体实现:
#include <math.h>
#include <algorithm>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <stdlib.h>
#include <cstdlib>
#include <cstring>
//#include "./include/list/sqlist.h"
using namespace std;
/**
* @description: 时间复杂度O(2^n) + 空间复杂度O(n)
* @param {int} month
* @return {*}
*/
int GetRabbitNums(int month){
//典型递归题目
//设置终止条件
if(month == 1 || month == 2) return 1;
else return GetRabbitNums(month-2)+GetRabbitNums(month -1);
}
//法2迭代法
/**
* @description: 时间复杂度O(n) + 空间复杂度O(1)
* @param {int} month
* @return {*}
*/
int GetRabbitNumsII(int month){
//设置k1,k2,k3
int k1 = 1;//第一个月
int k2 = 1;//第二个月
int ans = 0;//输出对应月份的答案
if(month == 1 || month == 2) return 1;
for(int i = 3; i <= month; i++){
ans = k1 + k2;//累计答案
k1 = k2;//更新第i-2个月的答案
k2 = ans;//更新第i-1个月的答案
}
return ans;
}
int main(){
// //day06
// LinkList L;
// int n;//输入数据数量
// int index = 0;//输入的位置
// ListNode* p;
// while(scanf("%d",&n) != EOF){
// L = ListTailInsert(L,n);
// scanf("%d",&index);
// if(index == 0) std::cout << 0 << std::endl;
// else{
// p = FindKInListIII(L,index);
// if(p != NULL) printf("%d\n",p->data);
// }
// //PrintLinkedList(L);
// }
int month_;
while(scanf("%d",&month_) != EOF){
int ans = GetRabbitNumsII(month_);
printf("%d\n",ans);
}
system("pause");
return 0;
}
时间复杂度分析:
- 法1:时间:O(2^n),空间O(n),证明连接
- 法2:时间:O(n),空间O(n)
小结:
这种类型的题就是需要找到递归思路,就是每一层的运算是不是重复的,假如是重复的,那么就符合递归逻辑,但是递归的时间效率一般较慢,且鲁棒性差