牛客爬楼梯

题目

链接:
爬楼梯
来源:牛客网

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

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

测试样例1:

1
返回:1

测试样例2:

3
返回:4

测试样例3:

4
返回:7

看完题心中一动!这道题我见过。好吧其实确实有一道类似的题,也是小孩子爬楼梯,只不过那个小孩一次移动1或者2步。这个小孩是1,2或者3步。

分析

思路:其实思路一样的。都可以用递归来写。
假如小孩第一步走了1步,那么还剩下(n-1)个台阶走,
假如小孩第一步走了2步,那么还剩下(n-2)个台阶走,
假如小孩第一步走了3步,那么还剩下(n-3)个台阶走。
小孩子的第一步也就这三种情况了,那么剩下的走法其实就是这三种加起来!
所以递归可以这样写:
不亏是你(递归)简洁

//递归写法
    public static int getCount(int n){
        if(n == 1){
            return 1;
        }else if(n == 2){
            return 2;
        }else if(n == 3){
            return 4;
        }else {
            return getCount(n-1)+getCount(n-2)+getCount(n-3);
        }
    }

但是递归计算慢也是出了名的。所以我们就不得不改成非递归了。而且还要避免数据溢出。

做过能走1或者2步的小孩的题的人,我们可以发现
那个小孩的走法组合起来就是斐波那契数列:

台阶 走法
1 1
2 2
3 3
4 5
5 8

同样的我们尝试这将可以走3步的小孩的走法总结一下:

台阶 走法
1 1
2 2
3 4
4 7
5 13

发现没:可以走三步的小孩的走法,也是个类似斐波那契数列的数列。斐波那契数列是前两个元素相加得到第三个。
而这个数列是前三个相加得到第四个。以此类推…

那么我们就可以尝试写代码了:

//计算
    public static int getCounts(int n){
        if(n == 1){
            return 1;
        }else if(n == 2){
            return 2;
        }else if(n == 3){
            return 4;
        }else {
            int first = 1;
            int second = 2;
            int third = 4;
            int forth = 0;
            while (n - 3 > 0) {
                forth = ((first + second)%1000000007+third%1000000007)%1000000007;
                first = second;
                second = third;
                third = forth;
                n--;
            }
            return forth;
        }
    }

这里比较难懂的是:

forth = ((first + second)%1000000007+third%1000000007)%1000000007

这一句原句是这样的:
因为为了防止数据溢出,题目要求将
结果 mod 1000000007

forth = (first + second+third)%1000000007;

但是这样还是会溢出,所以就需要再改造!
牛客评论区发现了对这句话的解释
再加上网上查询得出:
(a + b)% c == (a % c + b % c) % c
所以我们可以将(first+second+third)% 1000000007
改为上述所写!

至此主要算法就写完了。
下面是通过的代码。

代码

import java.util.*;

public class GoUpstairs {
    //计算
    public static int getCounts(int n){
        if(n == 1){
            return 1;
        }else if(n == 2){
            return 2;
        }else if(n == 3){
            return 4;
        }else {
            int first = 1;
            int second = 2;
            int third = 4;
            int forth = 0;
            while (n - 3 > 0) {
                forth = ((first + second)%1000000007+third%1000000007)%1000000007;
                first = second;
                second = third;
                third = forth;
                n--;
            }
            return forth;
        }
    }
    public int countWays(int n) {
        // write code here
        return getCounts(n);
    }
}
发布了57 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42419462/article/details/104831450
今日推荐