C/C++ 算法入门:一维动态规划基础实战
动态规划(Dynamic Programming)是算法面试中的高频考点,也是很多初学者感到棘手的部分。其实掌握核心思路后,它并没有想象中那么难。本文将通过四道经典的一维动态规划题目,带你从状态定义到代码实现,逐步建立解题框架。
核心方法论
动态规划的本质可以概括为:状态定义 + 状态转移方程 + 初始条件 + 状态存储。在实战中,我们通常遵循以下五个步骤来拆解问题:
- 状态表示:明确
dp[i]的含义。通常是以位置i结尾或开头的某种最优解或方案数。 - 状态转移方程:推导
dp[i]与之前状态的关系。这是最关键的一步,往往需要结合题目约束进行逆向思考。 - 初始化:确定边界值,确保递推过程不越界。
- 填表顺序:根据依赖关系决定遍历方向(如从左向右、从右向左)。
- 返回值:根据题意从
dp表中提取最终结果。
提示:在处理数字字符判断时,建议转换为整型后再比较,避免字符编码带来的逻辑漏洞。适当开辟虚拟节点空间往往能简化边界处理。
实战演练
1. 第 N 个泰波那契数
题目描述:计算第 n 个泰波那契数,其中 T0 = 0, T1 = 1, T2 = 1, Tn+3 = Tn + Tn+1 + Tn+2。
思路分析:
这是一个典型的线性递推问题。状态 dp[i] 直接定义为第 i 个泰波那契数。转移方程即为 dp[i] = dp[i-1] + dp[i-2] + dp[i-3]。由于计算当前项只依赖前三项,我们可以使用滚动数组将空间复杂度优化至 O(1)。
代码实现:
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 ret = 0;
for ( i = ; i <= n; ++i) {
ret = a + b + c;
a = b;
b = c;
c = ret;
}
ret;
}
};


