[蓝蓝计算机考研算法]-day7统计每个月兔子的总数

113 阅读2分钟

题目描述

有一种兔子,从出生后第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 天,点击查看活动详情