青蛙跳台阶问题

1.问题描述

一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法。

2.分析

  • 如果只有一个台阶,即n=1,那么显然就一种跳发,f(n) = 1 (n=1)
  • 如果有两个台阶,即n=2,那么有两种跳发:一种是跳两次,每次跳1级;一种是跳一次,跳2级。f(n) = 2 (n=2)
  • 如果有台阶数大于等于3,即n>=3,那又该怎么跳?。我们可以逆序思维,假设我们第一跳是跳1级,那么,之后我们需要跳n-1级台阶,即f(n-1);如果我们第一跳是跳2级,那么,,之后我们需要跳n-2级台阶,即f(n-2)。所以f(n)=f(n-1)+f(n-2)。
    即:
f(1) = 1;
f(2) = 2;
f(n) = f(n-1)+ f(n-2);//著名的斐波那契数列

3.递归方法

long long frog_fun1(int n)
{
    if(n <=0 )
        return 0;
    if(n == 1)
        return 1;
    if(n == 2)
        return 2;
    return frog_fun1(n-1)+frog_fun1(n-2);
}

时间复杂度O(2^n),空间复杂度O(n)。

4.改进版递归

long long forg_fun3_result(vector<long long>& r,int n)
{
    if(r[n]!=-1)
        return r[n];

    if(n >= 3)
        r[n] = forg_fun3_result(r,n-1)+forg_fun3_result(r,n-2);


    return r[n];
}
long long forg_fun3(int n)
{
    if(n <= 0)
        return 0;
    if(n == 1)
        return 1;
    if(n ==2)
       return 2;
    vector<long long> r(n+1,-1);
    r[0] = 0; 
    r[1] = 1;
    r[2] = 2;
    return forg_fun3_result(r,n);

}

时间复杂度O(n),空间复杂度O(n)。

  • 这使用了一个辅助函数,一个辅助空间。使用了递归,f(n),f(n-1)…f(1)会依次调用,分别赋值,当下一次在调用f(n-1)..f(1)的时候,因为vector保存了数据,所以就不继续迭代。所以时间复杂度是O(n)。
  • 使用了一个辅助空间,要使用n个空间,递归的时候,深度为n,所以空间复杂度O(n).

5.迭代实现

long long frog_fun2(int n)
{

    int result[] = {0,1,2};
    if(n < 0)
        return result[0];
    if(n <3)
        return result[n];

    long long frog_one = 2;
    long long frog_two = 1;
    long long frog_result = 0;
    for(int i=3;i <=n ;++i)
    {
        frog_result = frog_one + frog_two;
        frog_two = frog_one;
        frog_one = frog_result;
    }
    return frog_result;

}

其实还有一种,使用矩阵方法,具体实现这里就不说了
这里写图片描述

6.完整代码

#include <iostream>
#include <vector>
using std::vector;
using std::cout;
using std::endl;

long long frog_fun1(int n)
{
    if(n <=0 )
        return 0;
    if(n == 1)
        return 1;
    if(n == 2)
        return 2;
    return frog_fun1(n-1)+frog_fun1(n-2);
}
long long frog_fun2(int n)
{

    int result[] = {0,1,2};
    if(n < 0)
        return result[0];
    if(n <3)
        return result[n];

    long long frog_one = 2;
    long long frog_two = 1;
    long long frog_result = 0;
    for(int i=3;i <=n ;++i)
    {
        frog_result = frog_one + frog_two;
        frog_two = frog_one;
        frog_one = frog_result;
    }
    return frog_result;

}

long long forg_fun3_result(vector<long long>& r,int n)
{
    if(r[n]!=-1)
        return r[n];

    if(n >= 3)
        r[n] = forg_fun3_result(r,n-1)+forg_fun3_result(r,n-2);


    return r[n];
}
long long forg_fun3(int n)
{
    if(n <= 0)
        return 0;
    if(n == 1)
        return 1;
    vector<long long> r(n+1,-1);
    r[0] = 0; 
    r[1] = 1;
    r[2] = 2;
    return forg_fun3_result(r,n);

}


void Test(int n)
{
    cout<<"("<<n<<"):"<<":"<<frog_fun2(n)<<":"<<forg_fun3(n)<<endl;
    //cout << "frog_fun1:"<<frog_fun1(n)<<endl;
}
int main()
{
    for(int i=-1;i <40;++i)
    {
        Test(i);
    }
    return 0;
}

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值