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

来源:互联网 发布:怎么防盯盯软件 编辑:程序博客网 时间:2024/06/05 10:27

跳台阶

1. 题目

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

2. 思路

只有两种可能,即跳1级或2级。| 阶梯级数 | 跳台阶的可能性 | 跳法数目 || 1  | 1 | 1 || 2 | 112| 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]表示跳到第n阶台阶所花费的步数的所有可能性。​第一次只可以跳12 阶,分别对每一种情况进行考虑。​若第一次跳了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[n];        return ans;    }};

变态跳台阶

1. 题目

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

2. 思路

​比跳台阶难的地方就在于每次不仅可以跳1阶和2阶,而是可以跳不超过阶梯数目的任意阶数。​对于n阶台阶,还是考虑跳第一次的情形:​令a[n]表示跳到第n阶台阶所花费的步数的所有可能性。​第一次可以跳12...,n阶,分别对每一种情况进行考虑。​若第一次跳了1阶,那么剩下需要跳a[n-1]次;​若第一次跳了2阶,那么剩下需要跳a[n-2]次;​若第一次跳了3阶,那么剩下需要跳a[n-3]次;​...​若第一次跳了n-1阶,那么剩下需要跳a[n-(n-1)]=a[1]次;​这样就考虑完了所有情况。​综上所述,总共能够跳的可能性有:a[n] = ​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[n] = 2 * a[n-1];​ps:​一开始没有想到这种方法,而是硬找出前几项的可能性,试探性地找出规律:​a[1] = 1;​a[2] = 2;​a[3] = 4;​a[4] = 8;​a[5] = 16;​似乎可以找到这么个规律:a[n] = 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;    }};
原创粉丝点击