通过上道题我认识到 从文字 向数字转变的能力在做题中是非常重要的,所以我向ai问这样类似的情况还有哪些,他给我的答复
有的,而且这类能力非常重要。你说的"来源合并",本质是:
把题目里的文字关系,翻译成数学关系。
刷算法题时,常见的"文字 → 数学思维"大概有下面几类。
1. "从哪里来"思维:来源合并
这是网格 DP、路径 DP 最常见。
题目文字:
只能向右或向下走
数学翻译:
当前位置只能从上面来,或者从左边来
如果题目问"多少种":
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
如果题目问"最小路径和":
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
记忆:
求数量:来源相加
求最小:来源取 min
求最大:来源取 max
2. "走到这里"思维:定义状态
很多题第一步不是写代码,而是先定义:
dp[i] 或 dp[i][j] 表示什么?
例如:
不同路径
dp[i][j] = 走到第 i 行第 j 列有多少种方法
最小路径和
dp[i][j] = 走到第 i 行第 j 列的最小路径和
最长递增子序列
dp[i] = 以 nums[i] 结尾的最长递增子序列长度
记忆:
题目问什么,dp 就尽量定义成什么。
3. "最后一步"思维
这是 DP 里非常重要的思维。
不是从头想,而是反过来问:
到达当前状态之前,最后一步可能是什么?
比如「爬楼梯」:
题目文字:
每次可以爬 1 阶或 2 阶
数学翻译:
到第 i 阶,最后一步可能从 i-1 来,也可能从 i-2 来
所以:
dp[i] = dp[i - 1] + dp[i - 2];
再比如「完全平方数」:
凑成 i,最后一次可能用了 1、4、9、16...
所以:
dp[i] = Math.min(dp[i], dp[i - square] + 1);
记忆:
想不出来时,就问:最后一步从哪里来?
4. "选或不选"思维
看到数组、子序列、背包,经常用这个。
题目文字:
每个数可以选择,也可以不选择
数学翻译:
当前元素有两个选择:选 / 不选
比如 0-1 背包:
不选当前物品:dp[i - 1][j]
选当前物品:dp[i - 1][j - weight] + value
所以:
dp[i][j] = Math.max(
dp[i - 1][j],
dp[i - 1][j - weight] + value
);
记忆:
看到"子序列、选一些数、能不能凑成",先想选或不选。
5. "分割点"思维
看到字符串拆分、区间问题,经常用这个。
题目文字:
一个字符串能不能被拆成字典里的单词
数学翻译:
枚举最后一个单词从哪里开始
例如「单词拆分」:
s[0...i] 能不能拆
看是否存在一个 j:
s[0...j] 能拆,并且 s[j...i] 是字典单词
代码公式:
if (dp[j] && wordSet.contains(s.substring(j, i))) {
dp[i] = true;
}
记忆:
看到"拆分、切割、分段",就枚举分割点 j。
6. "连续一段"思维:前缀和
看到"区间和""连续子数组和",经常用前缀和。
题目文字:
求 nums[l] 到 nums[r] 的和
数学翻译:
区间和 = 前缀和相减
公式:
sum(l, r) = prefix[r + 1] - prefix[l];
记忆:
连续区间求和,不要每次重新加,用前缀和相减。
7. "满足条件的两个数"思维:哈希表
看到:
找两个数,使它们加起来等于 target
数学翻译:
当前数是 x,我需要找 target - x
比如两数之和:
need = target - nums[i];
然后用哈希表判断 need 是否出现过。
记忆:
找配对,就把问题变成"我现在还缺谁"。
8. "最大/最小"思维:维护最优值
题目文字:
求最大值、最小值、最长、最短
数学翻译:
每一步更新当前最优答案
例如最大子数组和:
cur = Math.max(nums[i], cur + nums[i]);
ans = Math.max(ans, cur);
意思是:
要么从当前数重新开始
要么接在之前后面
记忆:
求最优,就问当前位置要不要继承前面的结果。
9. "有序数组"思维:双指针 / 二分
看到:
数组有序
就要敏感。
如果找两个数:
小了,左指针右移
大了,右指针左移
如果找某个边界:
用二分
记忆:
题目说有序,通常不是白说的。
10. 最重要的总口诀
你可以这样记:
求多少种:加法
求最小最大:min / max
求能不能:boolean true / false
求连续区间:前缀和
求配对:哈希表找差值
求路径:问当前位置从哪里来
求子序列:问当前元素选不选
求拆分:枚举分割点
求最短步数:BFS
求所有可能:回溯
真正刷题时,你就按这个顺序问自己:
1. 题目问什么?数量 / 最小 / 最大 / 是否存在?
2. 当前状态是什么?
3. 当前状态从哪里来?
4. 多个来源怎么合并?加法 / min / max / true false?
对你现在正在学的 DP 题来说,最重要的是这一句:
文字里说"只能从哪里走",代码里就写"当前位置从哪些来源转移过来"。