当前位置: 首页 > news >正文

经典动态规划题解

目录

 1. 1137. 第 N 个泰波那契数

2. 746. 使用最小花费爬楼梯 

3. 746. 爬楼梯的变异:三步问题(waysToStep)

4. 91. 解码方法

总结:动态规划的通用解题步骤


动态规划(DP)是算法中的重要思想,核心是“用已求结果推导当前结果”,常能将暴力解法的高复杂度优化为线性。本文通过四道经典题目,拆解DP的基础思路与避坑要点。

 1. 1137. 第 N 个泰波那契数

题目核心
 
求泰波那契数列的第n项,数列定义为: T(0)=0,T(1)=1,T(2)=1,T(n)=T(n-1)+T(n-2)+T(n-3) (n≥3)。
 
解题思路
 
- 状态定义:无需额外DP数组,用三个变量 a、b、c 分别代表 T(n-3)、T(n-2)、T(n-1) ,通过迭代更新变量值,避免空间浪费。
- 递推逻辑:从n=3开始,每次计算 T(n)=a+b+c ,再将 a→b 、 b→c 、 c→T(n) ,逐步推进到第n项。
- 边界处理:直接判断n=0、1、2的情况,返回固定值,避免进入循环。

 
代码实现

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;for(int i=3;i<=n;i++){int d = a + b + c;a = b;b = c;c = d;}return c;}
};

易错点
 
- 无需用数组存储所有项:新手易习惯性定义 dp[n] 数组,但本题只需前三项结果,用变量迭代可将空间复杂度从O(n)降至O(1)。

2. 746. 使用最小花费爬楼梯 


题目核心
 
楼梯有n阶,每次可爬1或2阶,每阶对应“爬上去的成本” cost[i] ,求到达楼顶(第n阶,无成本)的最小成本。
 
解题思路
 
- 状态定义: dp[i] 表示到达第i阶的最小成本。
- 递推逻辑:到达第i阶只有两种路径:
1. 从第i-1阶爬1阶,成本为 dp[i-1] + cost[i-1] ( cost[i-1] 是第i-1阶的成本);
2. 从第i-2阶爬2阶,成本为 dp[i-2] + cost[i-2] 。
取两者最小值作为 dp[i] ,即 dp[i] = min(dp[i-1[icost[i-1], dp[i-2[icost[i-2]) 。
- 边界处理: dp[0] = 0 (起点在第0阶,无需成本)、 dp[1] = 0 (可直接从第0阶或第1阶起步,均无额外成本)。

 
代码实现

class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {int n = cost.size();vector<int> dp(n+1);for (int i = 2; i <= n; i++)dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);return dp[n];}
};

易错点
 
- 混淆“阶数”与“cost数组下标”:楼顶是第n阶,对应 dp[n] ,而 cost 数组仅到 cost[n-1] (第n-1阶的成本),需避免下标越界。
- 初始状态错误:部分人会将 dp[1] 设为 cost[0] ,但题目允许从第1阶直接起步,无需先爬第0阶,因此 dp[1] 应为0。

3. 746. 爬楼梯的变异:三步问题(waysToStep)

题目核心
 
求爬到n阶台阶的方法数,每次可爬1、2或3阶,结果需对 1e9+7 取模(防止溢出)。
 
解题思路
 
- 状态定义: dp[i] 表示爬到第i阶的总方法数。
- 递推逻辑:到达第i阶的路径来自前3阶(爬1阶到i、爬2阶到i、爬3阶到i),因此 dp[i] = dp[i-1] + dp[i-2] + dp[i-3] 。
- 边界处理: dp[1]=1 、 dp[2]=2 、 dp[3]=4 (直接枚举所有可能路径)。
- 溢出处理:n较大时(如n=1e6),结果会超出 int 范围,需用 long long 存储中间值,并每次计算后取模。

 
代码实现

class Solution {
public:int waysToStep(int n) {if (n == 1) return 1;if (n == 2) return 2;if (n == 3) return 4;long long a = 1, b = 2, c = 4;long long d;for (int i = 4; i <= n; ++i) {d = (a + b + c) % 1000000007;a = b;b = c;c = d;}return c;}
};

 易错点
 
- 未处理数值溢出: int 最大约2e9,当n≥30时,方法数会超过 int 范围,必须用 long long 存储中间变量,且每次计算后取模(而非最后取模,避免中间值溢出)。
- 边界值记忆错误:易将 dp[3] 误记为3(忽略“1+1+1”“1+2”“2+1”“3”四种路径),需准确枚举初始值。

4. 91. 解码方法

题目核心
 
将字符串 s (仅含数字)解码为字母(A=1,B=2,…,Z=26),求总解码方法数。
 
解题思路
 
- 状态定义: dp[i] 表示字符串前i个字符( s[0..i-1] )的解码方法数。
- 递推逻辑:分两种情况判断当前字符的解码方式:
1. 单个字符解码:若 s[i-1] != '0' (0无法单独解码),则 dp[i] += dp[i-1] (前i-1个字符的方法数可直接延续);
2. 两个字符解码:若前两个字符组成的数字 t 满足 10≤t≤26 (如“12”可解为L,“27”不可解),则 dp[i] += dp[i-2] (前i-2个字符的方法数延续)。
- 边界处理:
-  dp[0] = 1 (空字符串有1种解码方式,作为递推基础);
-  dp[1] = (s[0] != '0') ? 1 : 0 (单个字符若为0则无法解码)。

 
代码实现

class Solution {
public:int numDecodings(string s) {int n=s.size();vector<int>dp(n+1);dp[0]=1; // 空字符串的解码方法数dp[1]=s[0]!='0'; // 单个字符的解码情况if(n==1)return dp[1];for(int i=2;i<=n;i++){// 单个字符解码if(s[i-1]!='0')dp[i[i=dp[i-1];// 两个字符解码int t=(s[i-2]-'0')*10+(s[i-1]-'0');if(t>=10&&t<=26)dp[i[i=dp[i-2];}return dp[n];}
};

易错点
 
- 忽略“0”的特殊处理:
- 单个“0”无法解码,若 s[i-1] == '0' ,则不能用单个字符解码;
- 两个字符中,若前一个是“0”(如“06”),组成的数字是6,不满足 10≤t≤26 ,无法解码。
- 边界 dp[0] 的意义:新手易忽略 dp[0]=1 ,但当i=2且两个字符可解码时(如“12”), dp[2] = dp[1] + dp[0] , dp[0] 的1是“空字符串+两个字符”的解码方式基础。
- 字符串下标与 dp 下标错位: dp[i] 对应前i个字符( s[0] 到 s[i-1] ),计算两个字符时需取 s[i-2] 和 s[i-1] ,避免下标越界。

总结:动态规划的通用解题步骤

1. 定义状态:明确 dp[i] 代表的具体含义(如“到第i阶的方法数”“前i个字符的解码数”);
2. 推导递推公式:找到“当前状态与前几个状态的关系”(如泰波那契是前3项和,解码是单/双字符两种情况);
3. 处理边界条件:确定初始值(如 dp[0] 、 dp[1] ),避免递推起始错误;
4. 优化空间(可选):若递推仅依赖前k个状态(如泰波那契依赖前3个),可用变量代替数组,将空间复杂度从O(n)降至O(1);
5. 规避特殊情况:如数值溢出(取模、用 long long )、无效输入(如“0”“27”)。

 
掌握这四道题的思路,可轻松应对大部分基础DP问题,后续复杂DP(如二维DP、状态压缩)也能以此为基础扩展。


文章转载自:

http://0HaOsc4f.mcpdn.cn
http://VlkNtIo1.mcpdn.cn
http://0vjTlvVV.mcpdn.cn
http://JTV1zAMs.mcpdn.cn
http://xf77mPnk.mcpdn.cn
http://whWDf9k0.mcpdn.cn
http://KxMwXlq4.mcpdn.cn
http://AAkFBEky.mcpdn.cn
http://fTPbcwjK.mcpdn.cn
http://WACxZotG.mcpdn.cn
http://9VGmgCXN.mcpdn.cn
http://MnYYj810.mcpdn.cn
http://6VvC2SPU.mcpdn.cn
http://64EjfGeA.mcpdn.cn
http://bQnUDYD3.mcpdn.cn
http://r0HBOYb0.mcpdn.cn
http://hOiKfGTi.mcpdn.cn
http://yjq7LQ3C.mcpdn.cn
http://iaMXSQ6k.mcpdn.cn
http://V5yrLiJR.mcpdn.cn
http://hq24hBUi.mcpdn.cn
http://SX74k5U9.mcpdn.cn
http://0tggIjiT.mcpdn.cn
http://phYQCx0m.mcpdn.cn
http://I3vWSTps.mcpdn.cn
http://ugGX0qeD.mcpdn.cn
http://lq7PwyNW.mcpdn.cn
http://B52cbQhb.mcpdn.cn
http://TSsKQl65.mcpdn.cn
http://JDO9E1kV.mcpdn.cn
http://www.dtcms.com/a/379981.html

相关文章:

  • 商城购物系统自动化测试报告
  • [工作表控件20] 拼音排序功能:中文数据高效检索实战指南
  • 9120 部 TMDb 高分电影数据集 | 7 列全维度指标 (评分 / 热度 / 剧情)+API 权威源 | 电影趋势分析 / 推荐系统 / NLP 建模用
  • 【Java】多态
  • LeetCode热题 438.找到字符中所有字母异位词 (滑动窗口)
  • 解决 N1 ARMBIAN Prometheus 服务启动失败问题
  • Linux 正则表达式详解(基础 + 扩展 + 实操)
  • 01.【Linux系统编程】Linux初识(Linux内核版本、基础指令、理论知识、shell命令及运行原理)
  • MATLAB 的无人机 PID 控制及智能 PID 控制器设计的仿真
  • D007 django+neo4j三维知识图谱医疗问答系统|3D+2D双知识图谱可视化+问答+寻医问药系统
  • 5G单兵图传 5G单兵 单兵图传 无线图传 无线图传方案 无人机图传解决方案 指挥中心大屏一目了然
  • npm / yarn / pnpm 包管理器对比与最佳实践(含国内镜像源配置与缓存优化)
  • 运维安全06 - 服务安全
  • nestjs(node.js) 跟 java 关于return 的JSON 数据转换
  • RabbitMQ---面试题
  • npm ERR! code CERT_HAS_EXPIRED
  • Windows、Linux 系统 nodejs 和 npm 版本更新及错误修复
  • 网站漏洞扫描要怎么处理?
  • 无线通信模块撑油库安全:传液位信号,简布线与后期维护工作
  • ruoyi-vue(十四)——前端框架及package.json,vite.config.js, main.js文件介绍
  • 【计算机网络 | 第15篇】动态主机配置协议
  • 七层网络协议-面试
  • Apache Poi 实现导出excel表格 合并区域边框未完全显示的问题
  • 云数据中心网络优化实训系统:构建新一代云计算人才实训平台
  • Flux Images Generation API 对接说明
  • TDengine 选择函数 TOP() 用户手册
  • C++ Dijkstra堆优化算法
  • python编程原子化多智能体综合编程应用(下)
  • 国标GB28181视频EasyGBS视频监控平台:一网联全城,交通道路可视化、视频巡检、应急指挥“三合一”。
  • 【React】React 哲学