dp反思与总结

通过上道题我认识到 从文字 向数字转变的能力在做题中是非常重要的,所以我向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 题来说,最重要的是这一句:

文字里说"只能从哪里走",代码里就写"当前位置从哪些来源转移过来"。

相关推荐
bug大湿1 小时前
麦阵波束算法——MVDR
算法·音频
简简单单做算法1 小时前
基于模糊神经网络的一维时间序列预测算法matlab仿真
神经网络·算法·matlab·一维时间序列预测·模糊神经网络
郝学胜-神的一滴1 小时前
干货版《算法导论》05:从集合接口到排序
开发语言·数据结构·c++·程序人生·算法·排序
BLSxiaopanlaile1 小时前
关于 lru 和 lfu算法的简单实现
算法
菜菜的顾清寒1 小时前
力扣Hot100(23)反转链表
算法·leetcode·链表
Michelle80231 小时前
基于随机森林的乳腺癌肿瘤分类实验
算法·随机森林·分类
Yvonne爱编码1 小时前
机器学习---聚类四大算法完整实验教程(层次 / K-Means/GMM/ 谱聚类)
算法·机器学习·聚类
東隅已逝,桑榆非晚1 小时前
C语言内存函数
c语言·开发语言·笔记·算法
深蓝电商API1 小时前
爬虫代理IP智能调度:基于响应速度的实时评分算法
爬虫·算法