题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。
求该青蛙跳上一个n级的台阶总共有多少种跳法。
解题思路
因为青蛙一次可以跳1,2,3…n级台阶。
1. 求F(1),
青蛙跳一次1级台阶,
F(1) = 1 = 2
1−1
};
2. 求F(2),
青蛙在1级台阶{即F(1)},从1级台阶直接跳到2级台阶,跳法种类F(1);
青蛙直接从最下面跳到2级台阶,跳法种类1;
F(2)=F(1)+1 = 2 = 2
2−1
;
3. 求F(3),
青蛙在1级台阶{即F(1)},从1级台阶直接跳到3级台阶,跳法种类F(1);
青蛙在2级台阶{即F(2)},从2级台阶直接跳到3级台阶,跳法种类F(2);
青蛙直接从最下面跳到3级台阶,跳法种类1;
F(3)=F(2)+F(1)+1 = 4 = 2
3−1
;
4. 求F(4),
青蛙在1级台阶{即F(1)},从1级台阶直接跳到4级台阶,跳法种类F(1);
青蛙在2级台阶{即F(2)},从2级台阶直接跳到4级台阶,跳法种类F(2);
青蛙在3级台阶{即F(3)},从3级台阶直接跳到4级台阶,跳法种类F(3);
青蛙直接从最下面跳到4级台阶,跳法种类1;
F(4)=F(3)+F(2)+F(1)+1 = 8 = 2
4−1
;
5. 求F(5), 如上图
青蛙在1级台阶{即F(1)},从1级台阶直接跳到5级台阶,跳法种类F(1);
青蛙在2级台阶{即F(2)},从2级台阶直接跳到5级台阶,跳法种类F(2);
青蛙在3级台阶{即F(3)},从3级台阶直接跳到5级台阶,跳法种类F(3);
青蛙在4级台阶{即F(4)},从4级台阶直接跳到5级台阶,跳法种类F(4);
青蛙直接从最下面跳到5级台阶(虚线处),跳法种类1;
F(5)=F(4)+F(3)+F(2)+F(1)+1 = 16 = 2
5−1
;
求F(n),
青蛙先跳到1级台阶{即F(1)},从1级台阶直接跳到n级台阶,跳法种类F(1);
青蛙先跳到2级台阶{即F(1)},从2级台阶直接跳到n级台阶,跳法种类F(2);
青蛙先跳到3级台阶{即F(1)},从3级台阶直接跳到n级台阶,跳法种类F(3);
…
青蛙先跳到n-1级台阶{即F(n-1)},从n-1级台阶直接跳到n级台阶,跳法种类F(n-1);
青蛙直接从最下面跳到n级台阶,跳法种类1;
F(n)=F(n-1)+…+F(3)+F(2)+F(1)+1 = 2
n−1
;
参考代码
/*
计算F(n)= 2^(n-1)
在牛客网编译通过,有改动(类型int改为long double,用来测试这些算法能测试的极限)
思路:
1. 先求出2^n,再除以2.
2. 求2^n,相当于n个2相乘。
3. 举例说明,比如求2^99,即99个2相乘,即f(99)。
4. f(1)*f(1)=f(2); f(2)*f(2)=f(4); f(4)*f(4)=f(8); f(8)*f(8)=f(16);
f(16)*f(16)=f(32); f(32)*f(32)=f(64);
5. 步骤4中f(64)再平方一次,就能求出f(128),已经超过f(99),不能求出我们需要的值。
6. 步骤4后,只需要再求出f(99-64)=f(35),与f(64)相乘即可。
7. 同样的方法求f(35)。
优点:
循环,不耗费额外空间
缺点:
不如递归容易理解
代码不如递归清晰简洁
*/
long double jumpFloorII(int number) {
clock_t clockStart = clock();
cout << "clockStart1= " << clockStart << endl;
if ( number <= 0 ) {
return 0;
}
long double sum = 1.0;
long double tmpSum = 2.0;
int count = 1;
while ( count <= number ) {
count *= 2;
if ( count < number ) {
tmpSum *= tmpSum;
} else if ( count == number ) {
tmpSum *= tmpSum;//平方
sum *= tmpSum;
break;
} else {
count /= 2;
number -= count;
sum *= tmpSum;
if ( number == 1 ) {
sum *= 2;
break;
} else {
tmpSum = 2;
count = 1;
}
}
}
clock_t clockEnd = clock();
cout << "clockEnd1= "<< clockEnd <<endl;
cout << "clockTime1= "<< clockEnd-clockStart <<endl;
return sum/2.0;
}
an={a(n−1)/2∗a(n−1)/2∗a,an/2∗an/2,n为奇数n为偶数
/*
思路如上
*/
long double jumpFloorIII(int number) {
if ( number <= 0 ) {
return 0.0;
}
if ( number == 1 ) {
return 2.0;//递归出口
}
long double result = jumpFloorIII(number>>1);
result *= result;
if ( number & 1 ) {//奇数
result *= 2;
}
return result;
}
int _tmain(int argc, _TCHAR* argv[])
{
//-----------变态青蛙跳--------------------------
cout << jumpFloorII(1023) <<endl;
clock_t clockStart = clock();
cout << endl << endl;
cout << "clockStart2= " << clockStart << endl;
cout << jumpFloorIII(1022) <<endl;
clock_t clockEnd = clock();
cout << "clockEnd2= "<< clockEnd <<endl;
cout << "clockTime2= "<< clockEnd-clockStart <<endl;
int k = 0;
return 0;
}