题目描述
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。
一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?
数据范围:输入满足 1≤n≤31 题目来源
输入描述
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数
示例:
输入:3
输出:2
思路
-
列出每月兔子总数,找规律,可得出斐波那契数列 f(n)=f(n-1)+f(n-2) (除了前两个月是1,从第三个月开始,每月兔子数为前两月兔子数之和,即1、1、2、3、5、8... )
-
法1:递归 写一个递归方法,并调用。(递归方法里记得写递归出口)
-
法2:动态数组 定义一个动态数组,每个月的值由前两个月的值相加,然后for循环不断累计,最后求出n。
-
法3:迭代 定义三个变量来不断循环,求和,最终求出n。(空间复杂度最低)
具体实现
法1:递归
#include<iostream>
using namespace std;
int getSum(int n){ //求每月兔子数
if(n==1 || n==2) //递归出口
return 1;
return getSum(n-1)+getSum(n-2);
}
int main(){
int n;
while(cin>>n){
cout<<getSum(n);
}
// cin>>n;
// cout<<getSum(n);
}
法2:动态数组
#include<iostream>
#include<vector>
using namespace std;
int main(){
int n;
while(cin>>n){
vector<int> dp(n+1); //定义动态数组,用的是()不是[]
dp[1]=1;
dp[2]=1;
for(int i=3; i<=n; i++) //每个月的值不断累加
dp[i]=dp[i-1]+dp[i-2];
cout<<dp[n];
}
}
法3:迭代
#include<iostream>
using namespace std;
int main(){
int n;
while(cin>>n){
if(n<=2) cout<<1; //前两个月,直接输出
else{
int a=1,b=1,sum=0; //定义第一个月、第二个月、第三个月
for(int i=3; i<=n; i++){
sum=a+b; //相加求第三个月
a=b; //变量更新,然后循环
b=sum;
}
cout<<sum;
}
}
}
时间复杂度
法1:递归
-
时间复杂度:O(2的n次方),树型递归,遍历每个结点。
-
空间复杂度:O(n),递归栈,最大深度为n。
法2:动态规划
-
时间复杂度:O(n),遍历数组。
-
空间复杂度:O(n),数组长度为n。
法3:迭代
-
时间复杂度:O(n),遍历n个数。
-
空间复杂度:O(1),常数级空间。
小结
-
斐波那契数列:f(n)=f(n-1)+f(n-2),即前两个固定是1,第三个数为前两个之和,以此类推。(1,1,2,3,5,8,13...)
-
递归的空间复杂度为O(n),n为递归栈最大深度。
-
法1是最好想的,但是时间复杂度最大。法3时间复杂度最低,但是不好想。继续精进。
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 4 天,点击查看活动详情