一、题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
二、代码
版本1:未通过
原因:应该是因为时间复杂度比较高,所以没通过。
思路:利用递归进行处理。具体步骤如下:
S1:确定边界。当sum>target -->跳出;sum==target -->进行相加;
S2:确定递归表达式。sum<target -->进行尝试,跳1阶 or 2阶。
很多时候递归背后的思想是数学归纳法,利用归纳推出 f ( N ) f(N) f(N)与 f ( N − i ) f(N-i) f(N−i)的关系,写出递推表达式,然后据此就可以写出程序了。当然有时候没有清晰的表达形式,只是往下推,但也是递归。
代码:
public class Solution {
int sum=0, cnt=0;
public int JumpFloor(int target) {
if(sum>target) {
return 0;
}
if(sum==target) {
cnt++;
}
for(int i=1;i<=2;i++ ) {
if(sum<target) {
sum = sum + i;
JumpFloor(target);
sum = sum - i;
}
}
return cnt;
}
}
测试程序:
class Solution {
int sum=0, cnt=0;
public int JumpFloor(int target) {
if(sum>target) {
return 0;
}
if(sum==target) {
cnt++;
}
for(int i=1;i<=2;i++ ) {
if(sum<target) {
sum = sum + i;
JumpFloor(target);
sum = sum - i;
}
}
return cnt;
}
}
public class Main {
public static void main(String[] args) {
int f;
Solution solu = new Solution();
f = solu.JumpFloor(4);
System.out.println(f);
}
}
版本2:递归(自顶向下)
思路:现在假设已经到达目的地,倒推一下路径。现在站在N阶,往下跳有两种,跳1阶和跳两阶,所以 f ( N ) f(N) f(N) = f ( N − 1 ) f(N-1) f(N−1)+ f ( N − 2 ) f(N-2) f(N−2)。由此往下推,直到N=1或者N=2 跳出。
举个例子:当n=4时
f(4) = f(3)+f(2)
f(3) = f(2)+f(1)
f(2) = 2
f(1) = 1
==>
f(4) = f(3)+f(2) = 3 + 2 =5
f(3) = f(2)+f(1) = 3
递归表达式:
f
(
n
)
=
{
1
,
if n=1
2
,
if n=2
f
(
n
−
1
)
+
f
(
n
−
2
)
,
if n>2
f(n) = \begin{cases} \ 1, & \text{if n=1} \\[2ex] \ 2, & \text{if n=2} \\[2ex] f(n-1)+f(n-2), & \text{if n>2} \end{cases}
f(n)=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧ 1, 2,f(n−1)+f(n−2),if n=1if n=2if n>2
代码:
public class Solution {
public int JumpFloor(int target) {
if(target<=0) {
return 0;
} else if(target==1) {
return 1;
} else if(target==2) {
return 2;
} else {
return JumpFloor(target-1)+JumpFloor(target-2);
}
}
}
版本3:循环(自底向上)
思路:思想还是与递归思想一致,只不过是从底往上推导。当知道 N-1 个台阶与 N-2 个台阶的可能性的时候,就能确定第N个台阶的可能性了,即
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
f(n)=f(n-1)+f(n-2)
f(n)=f(n−1)+f(n−2)。
代码:
public class Solution {
public int JumpFloor(int target) {
int i, one=1, two=2, result=0;
if(target==0) {
return 0;
} else if(target==1) {
return 1;
} else if(target==2) {
return 2;
}
for(i=3;i<=target;i++) { // i:台阶数量
result = one + two;
one = two;
two = result;
}
return result;
}
}
三、小结
通过这个例子更加理解了递归,也发现讲清楚一个问题其实并不是很容易。