0
点赞
收藏
分享

微信扫一扫

中伟视界:智能识别!电动车戴头盔系统,保障您的安全出行

文章目录


在这篇博客中,我们将深入探讨动态规划算法在解决两个有趣问题上的应用:第 N 个泰波那契数(Tribonacci Number)和三步问题(Three Steps Problem)。这两个问题虽然表面不同,但它们的解决方案都可以通过动态规划的技术来优雅地实现。

第 N 个泰波那契数

题目链接:第 N 个泰波那契数 (https://leetcode.cn/problems/n-th-tribonacci-number/)

题目描述

泰波那契序列 Tn 定义如下:
T0 = 0, T1 = 1, T2 = 1
且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2。给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

输入样例

4

输出样例

4

数据规模与约定

0 <= n <= 37

答案保证是一个 32 位整数,即 answer <= 2^31 - 1。

解题思路

这个问题可以通过动态规划的方法来解决。动态规划是一种解决复杂问题的方法,通过将问题分解为更简单的子问题,并存储已解决子问题的解(通常是在一个数组中),从而避免重复工作。

对于泰波那契数列来说,我们可以创建一个数组 dp,其中 dp[i] 表示第 i 个泰波那契数。由于每个泰波那契数是前三个数的和,我们可以初始化前三个泰波那契数,然后用一个循环来计算后续的数值。

C++ 程序代码

方法一:使用动态规划数组
class Solution {
public:
    int tribonacci(int n) {
        // 边界条件处理
        if(n == 0) return 0;
        if(n == 1 || n == 2) return 1;

        // 初始化动态规划数组
        vector<int> dp(n + 1);
        dp[0] = 0;
        dp[1] = dp[2] = 1;

        // 使用动态规划公式填充数组
        for(int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
        }

        // 返回结果
        return dp[n];
    }
};
方法二:优化空间的动态规划
class Solution {
public:
    int tribonacci(int n) {
        // 边界条件处理
        if(n == 0) return 0;
        if(n == 1 || n == 2) return 1;

        // 初始化前三个泰波那契数
        int a = 0, b = 1, c = 1;
        
        // 用于临时存储计算结果
        int d = 0;

        // 通过迭代计算第 n 个泰波那契数
        for(int i = 3; i <= n; i++) {
            d = a + b + c;
            a = b;
            b = c;
            c = d;
        }

        // 返回结果
        return d;
    }
};

在上述两种方法中,第一种方法使用了一个与输入大小 n 相同的数组来存储中间结果。第二种方法则优化了空间复杂度,只使用了固定的几个变量来实现,这在 n 非常大时非常有用。

三步问题

题目链接:三步问题 (https://leetcode.cn/problems/three-steps-problem-lcci/)

题目描述

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

输入样例

3

输出样例

4

数据规模与约定

n 范围在 [1, 1000000] 之间

解题思路

这个问题与泰波那契数问题类似,也可以用动态规划来解决。在这个问题中,每一步小孩可以采取的操作有三种选择,因此当前的台阶数可以从前一步、前两步或前三步中的任何一个得到。我们可以用一个动态规划数组 dp 来存储到达每一阶楼梯的方法数,并用类似的方式来填充它。

C++ 程序代码

class Solution {
public:
    int waysToStep(int n) {
        const int MOD = 1000000007;
        // 边界条件处理
        if(n == 1 || n == 2) return n;
        if(n == 3) return 4;
        
        // 初始化动态规划数组
        vector<int> dp(n + 1);
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 4;

        // 使用动态规划公式填充数组
        for(int i = 4; i <= n; i++) {
            dp[i] = ((dp[i - 1] + dp[i - 2]) % MOD + dp[i - 3]) % MOD;
        }

        // 返回结果
        return dp[n];
    }
};

这段代码首先处理了一些边界条件,然后就是核心的动态规划逻辑。注意,在每次累加时,我们都需要对 MOD 取模,以防止结果溢出。

总结

在解决这两个问题时,我们使用了动态规划的方法,通过保存子问题的解来避免重复的工作。动态规划不仅可以帮助我们提高算法的效率,还可以让我们的代码更加简洁和易于理解。希望这篇博客能帮助你更好地理解动态规划,并在未来的编程挑战中应用这个强大的工具。

举报

相关推荐

0 条评论