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;
}