目录
1. 问题目标的区别
(1)找到最长的等差数列
(2)统计等差数列的个数
2. 填表顺序的区别
(1)固定倒数第二个数(i)
(2)固定倒数第一个数(j)
3. 核心区别总结
4. 为什么选择不同的固定方式?
5. 总结
1. 问题目标的区别
(1)找到最长的等差数列
-
目标:找到数组中最长的等差数列的长度。
-
特点:需要关注的是等差数列的长度,而不是具体的个数。
-
动态规划状态定义:
dp[i][j]表示以nums[i]和nums[j]结尾的等差数列的长度。 -
状态转移方程:
dp[i][j] = dp[k][i] + 1;其中
k是满足nums[k] = a且k < i的下标,a = 2 * nums[i] - nums[j]。
(2)统计等差数列的个数
-
目标:统计数组中所有等差数列的个数。
-
特点:需要关注的是等差数列的数量,而不是长度。
-
动态规划状态定义:
dp[i][j]表示以nums[i]和nums[j]结尾的等差数列的个数。 -
状态转移方程:
dp[i][j] += dp[k][i] + 1;其中
k是满足nums[k] = a且k < i的下标,a = 2 * nums[i] - nums[j]。
2. 填表顺序的区别
(1)固定倒数第二个数(i)
-
适用场景:找到最长的等差数列。
-
填表顺序:
-
外层循环固定
i(倒数第二个数)。 -
内层循环枚举
j(倒数第一个数)。
-
-
原因:
-
在计算
dp[i][j]时,需要依赖dp[k][i],其中k是i的前一个位置。 -
固定
i后,可以确保dp[k][i]在计算dp[i][j]时已经被计算。
-
-
示例代码:
for (int i = 1; i < n; i++) { // 固定倒数第二个数 for (int j = i + 1; j < n; j++) { // 枚举倒数第一个数 int a = 2 * nums[i] - nums[j]; // 计算前一个元素的值 if (hash.count(a)) { dp[i][j] = dp[hash[a]][i] + 1; // 更新 dp[i][j] } ret = max(ret, dp[i][j]); // 更新全局最大值 } }
(2)固定倒数第一个数(j)
-
适用场景:统计等差数列的个数。
-
填表顺序:
-
外层循环固定
j(倒数第一个数)。 -
内层循环枚举
i(倒数第二个数)。
-
-
原因:
-
在计算
dp[i][j]时,需要累加所有满足条件的dp[k][i],其中k是i的前一个位置。 -
固定
j后,可以确保在计算dp[i][j]时,所有可能的dp[k][i]已经被计算。
-
-
示例代码:
for (int j = 2; j < n; j++) { // 固定倒数第一个数 for (int i = 1; i < j; i++) { // 枚举倒数第二个数 long long a = (long long)nums[i] * 2 - nums[j]; // 计算前一个元素的值 if (hash.count(a)) { for (auto k : hash[a]) { if (k < i) { dp[i][j] += dp[k][i] + 1; // 更新 dp[i][j] } } } sum += dp[i][j]; // 累加 dp[i][j] 到 sum } }
3. 核心区别总结
| 区别点 | 固定倒数第二个数(i) | 固定倒数第一个数(j) |
|---|---|---|
| 适用场景 | 找到最长的等差数列 | 统计等差数列的个数 |
| 动态规划状态定义 | dp[i][j] 表示以 nums[i] 和 nums[j] 结尾的等差数列的长度 | dp[i][j] 表示以 nums[i] 和 nums[j] 结尾的等差数列的个数 |
| 状态转移方程 | dp[i][j] = dp[k][i] + 1 | dp[i][j] += dp[k][i] + 1 |
| 填表顺序 | 外层循环固定 i,内层循环枚举 j | 外层循环固定 j,内层循环枚举 i |
| 依赖关系 | 依赖 dp[k][i],其中 k 是 i 的前一个位置 | 依赖 dp[k][i],其中 k 是 i 的前一个位置 |
| 目标 | 找到最长的等差数列的长度 | 统计所有等差数列的个数 |
4. 为什么选择不同的固定方式?
-
固定倒数第二个数(
i):-
适用于最长等差数列问题,因为需要确保在计算
dp[i][j]时,dp[k][i]已经被计算。 -
通过固定
i,可以保证dp[k][i]在计算dp[i][j]时已经存在。
-
-
固定倒数第一个数(
j):-
适用于统计等差数列个数问题,因为需要累加所有可能的
dp[k][i]。 -
通过固定
j,可以确保在计算dp[i][j]时,所有可能的dp[k][i]已经被计算。
-
5. 总结
-
固定倒数第二个数:适用于最长等差数列问题,填表顺序是从左到右、从下到上。
-
固定倒数第一个数:适用于统计等差数列个数问题,填表顺序是从左到右、从上到下。
两者的选择取决于问题的目标和状态转移方程的依赖关系。通过合理的固定方式,可以确保动态规划的正确性和高效性。



















