题目:一只青蛙一次可以跳 1 级台阶,也可以跳 2 级。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
这道题还被 ITEye 放在了博文视点杯有奖答题活动里面。
我提供三种解法。
1、递归求解:
青蛙每跳一次前,有这样三种情况:
- (1)只剩 1 级或 0 级台阶了,只能跳一步或者无法再跳了,那么这条路也走到了终点,走法的种类数可以加 1;
- (2)可以走 2 级台阶;
- (3)可以走 1 级台阶。
于是递归方法求解:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/** * 递归方法 */ public static int calc( int n) { return recursiveCalc(n, 0 ); } private static int recursiveCalc( int n, int total) { if ( 1 == n || 0 == n) return ++total; total = recursiveCalc(n - 1 , total); return recursiveCalc(n - 2 , total); } |
2、概率论思路求解:
首先把问题抽象成简单的数学模型,设 2 步台阶跳了 x 次,1 步台阶跳了 y 次,那么:
2x + y = n
于是,当 x = i ,可知 x >= 0 ,且 x < n/2(向下取整),设某时刻的 x = i ,那么有 y = n – 2 * x ,于是,总共需要走 z = i + n – 2 * x 步。
这时,问题即转化为:
z 步骤中,有 x 个两步,y 个一步,相当于 z 个空当,由 x、y 去填充,那么不同填充方法的数目符合概率公式:
C(x,z) = z! / ((z-x)!x!)
即从排列 z 中取其中 x 个数的种类,x 内部无序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 概率论 */ public static int calc2( int n) { int total = 0 ; for ( int i = 0 ; i <= n / 2 ; i++) total += factorial((i) + (n - 2 * i)) / factorial(i) / factorial(n - 2 * i); return total; } private static int factorial( int n) { if ( 0 == n) return 1 ; int total = 1 ; for ( int i = 1 ; i <= n; i++) total *= i; return total; } |
3、数学归纳法求解:
如果 n=1,总步数 f(n)=1;如果 n=2,总步数 f(n)=2。
另一方面,当 n>=3,当前还剩的步数 f(n),如果接下去跳一步,那么还剩下的步数是 f(n-1);如果接下去跳两步,那么还剩下的步数是 f(n-2),故:f(n)=f(n-1)+f(n-2)。
现设 s3=f(n),s2=f(n-2),s1=f(n-1),从时间、空间复杂度来说,这也是最简单的一种方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 数学归纳法 */ public static int calc3( int n) { if ( 1 == n || 2 == n) return n; int s1 = 1 , s2 = 2 , s3 = 1 ; for ( int i = 3 ; i <= n; i++) { s3 = s1 + s2; s1 = s2; s2 = s3; } return s3; } |
聪明的你,还有什么办法?
欢迎和我讨论。 :)
—————————————————————————————————————-
补充:
跳到第 N 级话,
可以先跳 N-1 级,再跳 1 级;
也可以先跳 N-2 级,再跳 2 级。
所以 f(n)=f(n-1)+f(n-2),就是斐波那契数列。
既然都知道是斐波拉契数列了,那就给个通式吧:
F(N) =
((5+5^(1/2))/10)*(((1+5^(1/2))/2)^n) +
((5-5^(1/2))/10)*(((1-5^(1/2))/2)^n)
N >= 1
时间复杂度 O(log n),因为求一个数的 n 次方,可以以时间复杂度为 log n 的方式来计算求解。
文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》
概率论都出来了也太强了。。。本科的概率论已经忘光光,看不懂,膜拜
斐波那契数列的解法时间复杂度并不是 $O(1)$,而是 $log^n$,原因是通项公式中有一个 pwn(x, n) 的计算,这个函数的时间复杂度会是 $log^n$。
对。我修改一下
递归法和斐波那契数列方法非常不错!
其实不完全是斐波纳契数列,相当于是从斐波纳契数列的第二个数开始的一个数列。斐波纳契数列是 1,1,2,3,5,8, 而这道题是 1,2,3,5,8
碉堡了,我只能想到递归…http://50vip.com/blog.php?i=77
你这个验证码太难了~都没有评论的欲望了~