LeetCode | 面试题 08.01. 三步问题

相关标签

动态规划 DP、C 语言

题目描述

三步问题。有个小孩正在上楼梯,楼梯有 n 阶台阶,小孩一次可以上 1 阶、2 阶或 3 阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模 1000000007。

解题思路

这是一道基础动态规划题,根据 DP 的解题方法,我们将情况分为 n = 1, n = 2, n = 3 与 n > 3 四种情况讨论。

当 n 为 1 时,我们有且仅有最后一次上 1 阶楼梯这一种方法,f(1) = 1。

当 n 为 2 时,我们有最后一次上 1 阶楼梯和最后一次上 2 阶楼梯这两种方法,对应 f(2) = f(1) + 1 = 2。

当 n 为 3 时,我们有最后一次上 1 阶楼梯、最后一次上 2 阶楼梯和最后一次上 3 阶楼梯这两种方法,对应 f(3) = f(2) + f(1) + 1 = 4。

当 n 大于 3 时,小孩上到第 n 阶楼梯有 f(n) 种方法,按照最后一次抬腿上楼梯跨的阶数,可分为 “最后一次上 1 阶楼梯”、“最后一次上 2 阶楼梯” 和 “最后一次上 3 阶楼梯” 三种方法,对应的抬腿前已上台阶的方式数量为 f(n-1), f(n-2) 和 f(n-3),即 f(n) = f(n-1) + f(n-2) + f(n-3)。

按照以上思路写出代码如下:

int waysToStep(int n){
    if(n == 1){
        return 1;
    }
    else if(n == 2){
        return waysToStep(1) + 1;
    }
    else if(n == 3){
        return waysToStep(2) + waysToStep(1) + 1;
    }
    else{
        return (waysToStep(n - 1) + waysToStep(n - 2) + waysToStep(n - 3)) % 1000000007;
    }
}

执行后发现超时 😦

参考题解,对思路进行改进如下:
当 n = 4 时,f(4) = f(3) + f(2) + f(1)
当 n = 5 时,f(5) = f(4) + f(3) + f(2)
……
当 n = n 时,f(n) = f(n - 1) + f(n -2) + f(n - 3)

显然,对于每种阶数 n,上楼的方式仅取决于紧邻的前三种阶数的方式数量,且这三种方式的数量均出现在紧邻的前一种阶数的计算中,故设立一个四个元素大小的数组 kind 储存计算过程中的值,具体如下:

int waysToStep(int n){
    if(n < 3){
        return n;
    }
    if(n == 3){
        return 4;
    }
    //每增加一阶台阶,实现方法都是前三阶的方法数之和
    int *kind = (int*)malloc(sizeof(int) * 4);
    kind[0] = 1;
    kind[1] = 2;
    kind[2] = 4;
    for(int i = 3; i < n; ++i){
        kind[3] = (kind[0] + kind[1] + kind[2]) % 1000000007;
        for(int j = 0; j < 3; ++j){
            kind[j] = kind[j + 1];
        }
    }
    return kind[3];
}

执行后爆栈 😦

考虑到三个最大值可能为 1000000006 的数相加会超过 int 的范围,将 kind 数组的数据类型改为 long long,执行通过 😀

代码

int waysToStep(int n){
    if(n < 3){
        return n;
    }
    if(n == 3){
        return 4;
    }
    //每增加一阶台阶,实现方法都是前三阶的方法数之和
    long long *kind = (long long*)malloc(sizeof(long long) * 4);
    kind[0] = 1;
    kind[1] = 2;
    kind[2] = 4;
    for(int i = 3; i < n; ++i){
        kind[3] = (kind[0] + kind[1] + kind[2]) % 1000000007;
        for(int j = 0; j < 3; ++j){
            kind[j] = kind[j + 1];
        }
    }
    return kind[3];
}

请添加图片描述

posted @ 2023-10-04 16:57  Guanz  阅读(26)  评论(0编辑  收藏  举报  来源