一、先明确核心概念
理解 DP 复杂度前,得先搞清楚三个基础要素:
- 状态:DP 里定义的
dp[i]、dp[i][j]这类表示子问题的变量。比如dp[i]是第 i 个斐波那契数,dp[i][j]是前 i 个物品装容量 j 背包的最大价值。 - 状态数量:所有需要计算的子问题总数。一维 DP 通常是 n,二维 DP 则是 n*m。
- 单个状态计算成本:算一个状态(比如
dp[i])需要的操作数。通常是 O(1),少数情况会涉及循环导致 O(k)。
二、时间复杂度计算
核心公式很简单:时间复杂度 = 状态数量 × 单个状态的计算成本。
场景 1:一维 DP(如斐波那契数列)
int fib_dp(int n) {
if (n <= 2) return 1;
vector<int> dp(n+1);
dp[1] = 1;
dp[2] = 1;
for (int i=3; i<=n; i++) {
dp[i] = dp[i-1] + dp[i-2]; // 单次计算仅需一次加法
}
return dp[n];
}
这里状态是从 dp[3] 到 dp[n],约等于 O(n)。每个状态只需做一次加法,成本是 O(1)。所以总时间复杂度是 O(n)。
场景 2:二维 DP(如最小路径和)
int minPathSum(vector<vector<int>>& grid) {
int m = grid.size(), n = grid[0].size();
vector<vector<int>> (m, <>(n));
dp[][] = grid[][];
( j=; j<n; j++) dp[][j] = dp[][j] + grid[][j];
( i=; i<m; i++) dp[i][] = dp[i][] + grid[i][];
( i=; i<m; i++) {
( j=; j<n; j++) {
dp[i][j] = (dp[i][j], dp[i][j]) + grid[i][j];
}
}
dp[m][n];
}

