首页 > 其他分享 >【动态规划之斐波那契数列模型】——累加递推型动态规划

【动态规划之斐波那契数列模型】——累加递推型动态规划

时间:2024-10-30 20:45:06浏览次数:5  
标签:台阶 int 解码 之斐波 cost return 那契 动态 dp

文章目录

第N个泰波那契数列

解题思路: 泰波那契数列的第 N 项定义为前面三项之和,即 T0 = 0, T1 = 1, T2 = 1,从 T3 开始,每一项都等于前三项的和。要找到第 N 项,可以使用动态规划逐步求解每个值直到 TN。

初始化 T0 = 0, T1 = 1, T2 = 1。
使用一个数组或三个变量记录最近三项的值。
从 T3 开始,利用递推公式 Tn = T(n-1) + T(n-2) + T(n-3) 计算到第 N 项。
返回结果。
时间复杂度为 O(n),空间复杂度为 O(1)(若只保留最近三项值)。

class Solution 
{
public:
    int tribonacci(int n) 
    {
        // 如果 n 等于 0,直接返回 0,因为 T0 = 0
        if(n == 0) return 0;
        // 如果 n 等于 1 或 2,返回 1,因为 T1 = T2 = 1
        if(n == 1 || n == 2) return 1;

        // 初始化前三项的值
        int a = 0, b = 1, c = 1, d = 0;
        // 从第 3 项开始计算到第 n 项
        for(int i = 3; i <= n; i++)
        {
            // 当前项 d 是前面三项的和
            d = a + b + c;
            // 更新前三项的值,将 a, b, c 滚动到下一个位置
            a = b; // 原 b 变成新的 a
            b = c; // 原 c 变成新的 b
            c = d; // 当前项 d 变成新的 c
        }
        // 返回第 n 项的值
        return d;
    }
};
class Solution 
{
public:
    int tribonacci(int n) 
    { 
        // 特殊情况处理
        if(n == 0) return 0;   // 当 n 为 0 时,返回 0
        if(n == 1 || n == 2) return 1;  // 当 n 为 1 或 2 时,返回 1

        // 定义 dp 数组,dp[i] 表示第 i 个泰波那契数
        vector<int> dp(n + 1);

        // 初始化前三项
        dp[0] = 0;
        dp[1] = 1;
        dp[2] = 1;

        // 从第 3 项开始,利用递推公式逐步计算泰波那契数
        for(int i = 3; i <= n; i++)
        {
            dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];  // 当前项等于前三项之和
        }

        // 返回第 n 项的泰波那契数
        return dp[n];
    }
};

面试题08.01.三步问题

解题思路: 在楼梯上每次可以选择走 1 步、2 步或 3 步,问走到第 n 级台阶有多少种不同的方法。这个问题可以看作一个动态规划问题。

定义 dp[i] 为到达第 i 级台阶的方法总数。
基础条件:dp[0] = 1(在起点不动算一种方法),dp[1] = 1,dp[2] = 2。
递推公式:dp[i] = dp[i-1] + dp[i-2] + dp[i-3],因为可以从前一、前二或前三个台阶到达。
从小到大依次计算 dp[i],最终得到 dp[n]。
时间复杂度为 O(n),空间复杂度也为 O(1)(只需记录前几项的值)。

class Solution 
{
public:
    int waysToStep(int n) 
    {
        // 定义取模常量,用于防止结果过大
        const int MOD = 1e9 + 7;
        // 定义 dp 数组,dp[i] 表示到达第 i 级台阶的方法数
        vector<int> dp(n + 1);

        // 处理特殊情况
        if(n == 1 || n == 2) return n; // 如果 n 是 1 或 2,直接返回 n
        if(n == 3) return 4;           // 如果 n 是 3,直接返回 4(方法有:1+1+1, 1+2, 2+1, 3)

        // 初始化前三个台阶的方法数
        dp[1] = 1;  // 到达第 1 级台阶只有 1 种方法
        dp[2] = 2;  // 到达第 2 级台阶有 2 种方法:1+1 或 2
        dp[3] = 4;  // 到达第 3 级台阶有 4 种方法:1+1+1, 1+2, 2+1, 3

        // 从第 4 级台阶开始,使用递推公式计算每一级台阶的方法数
        for(int i = 4; i <= n; i++)
        {
            // 当前台阶的方法数等于前一、前二和前三个台阶的方法数之和,并对 MOD 取模
            dp[i] = ((dp[i - 1] + dp[i - 2]) % MOD + dp[i - 3]) % MOD;
        }

        // 返回到达第 n 级台阶的方法数
        return dp[n];
    }
};

使用最小花费爬楼梯

解题思路: 每一步都有一个代价,从楼梯底部出发,最终要到达顶层。选择以最小代价到达顶层。

定义 dp[i] 为到达第 i 层的最小花费。
初始状态:dp[0] = cost[0],dp[1] = cost[1]。
递推公式:dp[i] = min(dp[i-1], dp[i-2]) + cost[i],即可以从前一层或前两层到达。
为了达到顶层,我们可以从 n-1 或 n-2 层爬上去,所以最终答案是 min(dp[n-1], dp[n-2])。
优化:我们可以仅用两个变量记录前两个状态值,进一步降低空间复杂度到 O(1)。

class Solution 
{
public:
    int minCostClimbingStairs(vector<int>& cost) 
    {
        int n = cost.size();
        // 定义 dp 数组,dp[i] 表示从第 i 级台阶出发到达楼顶的最小花费
        vector<int> dp(n);

        // 初始化最后两个台阶的花费
        dp[n - 1] = cost[n - 1]; // 从最后一级直接到达顶层的花费就是 cost[n-1]
        dp[n - 2] = cost[n - 2]; // 从倒数第二级直接到达顶层的花费就是 cost[n-2]

        // 从倒数第三个台阶开始向前计算每一级的最小花费
        for(int i = n - 3; i >= 0; i--)
        {
            // 当前台阶的最小花费等于当前台阶的成本加上从下一阶或下下阶出发的最小花费
            dp[i] = cost[i] + min(dp[i + 1], dp[i + 2]);
        } 

        // 返回从第 0 或第 1 个台阶出发的较小花费,因为可以从这两级开始攀登
        return min(dp[0], dp[1]);
    }
};

解码问题

解题思路: 给定一个数字字符串,按字母表中的编码规则解码出不同的解码方式数量(如 A=1,B=2,… Z=26)。

定义 dp[i] 为长度为 i 的子字符串的解码方式数。
初始状态:dp[0] = 1(空字符串有一种解码方式,即不解码)。
递推公式:
若 s[i-1] 是一个有效的单个字符(非 0),则 dp[i] += dp[i-1]。
若 s[i-2:i] 是有效的双字符(10 到 26),则 dp[i] += dp[i-2]。
最终结果为 dp[n],即整个字符串的解码方式数。
该算法的时间复杂度为 O(n),空间复杂度也可以优化到 O(1)。

class Solution 
{
public:
    int numDecodings(string s) 
    {
        int n = s.size();
        // 定义 dp 数组,dp[i] 表示长度为 i 的子字符串的解码方法总数
        vector<int> dp(n + 1);
        
        // 初始状态:空字符串有一种解码方法
        dp[0] = 1;
        
        // dp[1] 取决于第一个字符是否为 '0',如果是 '0' 则没有解码方法
        dp[1] = s[0] != '0';

        // 从第二个字符开始遍历,逐步计算解码方法数
        for(int i = 2; i <= n; i++)
        {
            // 处理单独解码的情况,如果当前字符不为 '0',则可以单独解码
            if(s[i - 1] != '0') 
                dp[i] += dp[i - 1];

            // 处理两个字符组合解码的情况
            int a = (s[i - 2] - '0') * 10 + (s[i - 1] - '0'); // 计算当前和前一个字符组合的数值
            if(a >= 10 && a <= 26) 
                dp[i] += dp[i - 2];
        }

        // 返回整个字符串的解码方法总数
        return dp[n];
    }
};

标签:台阶,int,解码,之斐波,cost,return,那契,动态,dp
From: https://blog.csdn.net/ZWW_zhangww/article/details/143374386

相关文章

  • 代码随想录 -- 动态规划 -- 01背包理论基础
    46.携带研究材料(第六期模拟笔试)思路:dp[i][j]含义:在(0,i)之间任意选取物品放入容量为j的背包中,使背包的价值最大。递推公式:当前背包容纳不下第i个物品,不选第i个物品,此时背包的价值:dp[i][j]=dp[i-1][j]。当前背包容纳得下第i个物品时,且选择第i个物品,此时背包的价值:dp[i][j......
  • JDK和CGLIB动态代理技术的适用场景和特点
    区别项目JDK动态代理CGLIB动态代理代理原理基于接口(Interface)基于字节码生成(Subclassing)实现方式使用 java.lang.reflect.Proxy 类使用 net.sf.cglib.proxy.Enhancer 类被代理类要求必须实现一个或多个接口可以代理没有实现接口的类,可以是普通类......
  • mybatis动态SQL
    目前项目中写动态SQL,用的都是下面的语法:@Select("<script>"+"SELECTwr.id,wr.customer_id,wr.type,wr.detailfromxxxrel"+"LEFTJOINxxxwronrel.rule_id=wr.idwhererel.entity_id=#{entityId}andwr.customer_id=#{......
  • (系列十)Vue3中菜单和路由的结合使用,实现菜单的动态切换(附源码)
    说明  该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。   该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。   说明:OverallAuth2.0是一个简单、易懂、功能强大的权限+可视化流程管理系统。友情提醒:本篇文章是属于系......
  • 动态规划题解报告
    Findacar注意到矩阵本质上是一个分形,即每次向右下复制当前矩阵,证明考虑归纳法。由此可以知道一个比较好的性质\(a_{i+k,j+k}=a_{i,j}\)其中\(k=2^n\),由于每次是复制加倍,所以横纵坐标都会加上一个\(2^n\),且每次增加的二次幂一定是横纵坐标二进制减一后没有的那一位(证明考虑......
  • 明火识别视频分析服务器区域入侵智慧园区安防视频监控及动态布控预警方案
    智慧园区安防视频监控及动态布控预警方案是一种综合性的安全管理解决方案,它通过结合视频监控技术、人工智能算法、大数据分析等技术,实现视频分析服务器对工厂区域内人、车、物的全面监控和管理。一、需求和目标系统建设目标:搭建重点部位人脸识别动态布控系统平台,建立动态人脸......
  • 为.Net项目添加动态库加载路径
    为.Net项目添加动态库加载路径_51CTO博客_linux动态库加载路径本文分别基于.NetFramework和.NetCore的WPF应用程序为例,来说明如何为.Net项目添加自定义动态库加载路径。本文基于.NetCore创建WPF时,使用了.Net5作为目标框架。1、.NetFramework在基于.NetFramework的WPF项目......
  • LeetCode Hot 100:多维动态规划
    LeetCodeHot100:多维动态规划62.不同路径思路1:动态规划classSolution{public:intuniquePaths(intm,intn){if(m==1||n==1)return1; //dp[i][j]:到达(i,j)的不同路径数vector<vector<int>>dp(m+1,vec......
  • 06.动态代理设计模式
    06.动态代理设计模式目录介绍01.为何要动态代理1.1为何要动态代理1.2动态代理思考02.动态代理的概念2.1动态代理定义2.2动态代理类比理解2.3动态代理参与者2.4动态代理步骤03.动态代理的实现3.1罗列一个场景3.2用一个例子理解代理3.3基于接口动态代......
  • selenium抓取动态网页数据
    1.selenium抓取动态网页数据基础介绍1.1什么是AJAXAJAX(AsynchronouseJavaScriptAndXML:异步JavaScript和XML)通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新,这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行局部更新。传统的网页(不使用Aj......