您的位置:首页 > 其它

【递推法】跳台阶/进阶跳台阶/变态跳台阶

2017-09-08 11:00 218 查看

跳台阶

1. 题目

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

2. 思路

只有两种可能,即跳1级或2级。
| 阶梯级数 | 跳台阶的可能性 | 跳法数目 |
| 1  | 1 | 1 |
| 2 | 11,2| 2 |
| 3 | 111,12,21|3|
| 4 | 1111, 121,112,211,22| 5|
...

因为以下所有的情况都是这样的,即**当第一次跳1阶,那么剩下n-1个台阶,跳法是F(n-1);当第一次跳2阶,那么剩下n-2个台阶,跳法是F(n-2)**。
这里给出更加清晰的解释:
​对于n阶台阶,还是考虑跳第一次的情形:
​令a
表示跳到第n阶台阶所花费的步数的所有可能性。
​第一次只可以跳1,2 阶,分别对每一种情况进行考虑。
​若第一次跳了1阶,那么剩下需要跳a[n-1]次;
​若第一次跳了2阶,那么剩下需要跳a[n-2]次;

这样我们就已经找到了所有的情况,因此可以找到这么一个递推关系式:
>**F(n) = F(n-1) + F(n-2)**


没错,这就是费波纳茨数列。实现起来也是十分容易的:

//https://www.nowcoder.com/questionTerminal/8c82a5b80378478f9484d87d1c5f12a4
//来源:牛客网
//非递归版本
class Solution {
public:
int a[50];
int ans;
int jumpFloor(int number) {
a[1] = 1;
a[2] = 2;
for(int i=3;i<=number;i++){
a[i] = a[i-1] + a[i-2];
}
ans = a[number];
return ans;
}
};

//递归版本:
class Solution{
public:
int jumpFloor(int number) {
if(number <= 0) return -1
if(number == 1) return 1;
if(number == 2) return 2;
else return jumpFloor(number-1) + jumpFloor(number-2);
}
};


进阶跳台阶

1. 题目

https://www.nowcoder.com/questionTerminal/7f0661ace6df48d0af3f924950d57126

来源:牛客网

有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶、3阶。请实现一个方法,计算小孩有多少种上楼的方式。为了防止溢出,请将结果Mod 1000000007

给定一个正整数int n,请返回一个数,代表上楼的方式数。保证n小于等于100000。

测试样例:

1

返回:1

2.思路

/*一开始看到,觉得很简单,就是爬楼梯呀。但是怎么也不对,提交后正确率一直是百分之十一点几。
看了评论才知道需要:
a[i]=((a[i-1]+a[i-2])%1000000007+a[i-3])%1000000007
取模运算有这样一个性质:(a+b)%c = ((a%c)+(b%c))%c
所以(a[i-1]+a[i-2])%1000000007就相当于(a[i-1]%X+a[i-2]%X)%X   用X代替1000000007
这样就使得a[i-1]、a[i-2]、a[i-1]+a[i-2]都没有溢出,之后再与a[i-3]相加之后取模,使得全部结果没有溢出。
*/
class GoUpstairs {
public:
int ans;
int a[100001];
int countWays(int n) {
// write code here
a[1] = 1;
a[2] = 2;
a[3] = 4;
for(int i=4;i<=n;i++){
a[i] = ((a[i-1] + a[i-2]) % 1000000007 + a[i-3]) % 1000000007;
}
ans = a
;
return ans;
}
};


变态跳台阶

1. 题目

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

2. 思路

​比跳台阶难的地方就在于每次不仅可以跳1阶和2阶,而是可以跳不超过阶梯数目的任意阶数。
​对于n阶台阶,还是考虑跳第一次的情形:
​令a
表示跳到第n阶台阶所花费的步数的所有可能性。
​第一次可以跳1,2,...,n阶,分别对每一种情况进行考虑。
​若第一次跳了1阶,那么剩下需要跳a[n-1]次;
​若第一次跳了2阶,那么剩下需要跳a[n-2]次;
​若第一次跳了3阶,那么剩下需要跳a[n-3]次;
​...
​若第一次跳了n-1阶,那么剩下需要跳a[n-(n-1)]=a[1]次;
​这样就考虑完了所有情况。
​综上所述,总共能够跳的可能性有:
a
= ​a[n-1] + a[n-2] + ... + a[2] + a[1];
​让我们化简一下,可以令n=n-1,显然有a[n-1] = a[n-2] + a[n-3] + ... + a[1],因此上式可以化简为:
a
= 2 * a[n-1];
​ps:
​一开始没有想到这种方法,而是硬找出前几项的可能性,试探性地找出规律:
​a[1] = 1;
​a[2] = 2;
​a[3] = 4;
​a[4] = 8;
​a[5] = 16;
​似乎可以找到这么个规律:a
= 2 * a[n-2] + a[n-1];
​试着提交一下,居然通过了。。​
​*/


​class Solution {
public:
int a[50];
int ans;
int jumpFloorII(int number) {
a[1] = 1;
a[2] = 2;
for(int i=3;i<=number;i++){
a[i] = a[i-1] + 2 * a[i-2];
}
ans = a[number];
return ans;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: