
维护一个dp[i]表示包含i位置的最大连续子数组和,
for循环到i,dp[i]等于num[i]与dp[i-1]+num[i]的最大值
维护一个ret作为返回值 在每次更新dp[i]时实时更新

逆向思维 维护两个dp 命名为f和g
f[i]表示以i位置为结尾的所有子数组的最大和
g[i]表示以i位置为结尾的所有子数组的最小和
动态规划之后取f[i]和sum-g[i]的最大值即可
值得注意的是如果全部都是负数 会错误
因此加一个判断 全都是负数就取f[i]最大值

多状态问题需要两个dp
一个f[i]记录以i位置结尾的最大值
一个g[i]记录以i位置结尾的最小值
更新时
如果nums[i]>0
f[i]会取到f[i-1]*nums[i]或nums[i]
不然
f[i]会取到g[i-1]*nums[i]
g[i]同理
f[i]等于g[i-1]*nums[i]与f[i-1]*nums[i]与nums[i]的最大值
g[i]等于f[i-1]*nums[i]与g[i-1]*nums[i]与nums[i]的最小值
返回最大的f[i]即可

上一题的变种 要求我们求长度
维护f[i]为以i结尾的乘积为正数子数组最大长度
维护g[i]为以i结尾的乘积为负数子数组最大长度
遍历nums[i]
nums[i]大于0时
f[i]=f[i-1]+1
如果g[i-1]==0,说明还没遇到过负数,g[i]=0
否则g[i]=g[i-1]+1
nums[i]小于0时
如果g[i-1]==0,说明还没遇到过负数,f[i]=0
否则f[i]=g[i]+1
g[i]=f[i-1]+1
同样一个变量跟踪记录最大值

dp[i]为以i结尾的等差数列个数
如果i,i-1,i-2构成了等差数列
则dp[i]=dp[i-1]+1
ret+=dp[i]
解释 因为1 2 3 4构成等差数列
则后面加一个数也能和前面的子数组构成等差数列
然后还有和前两个数构成的一个


两个dp
f为以i结尾而且为下降趋势的子数组的长度
g为以i结尾而且为上升趋势的子数组的长度
遍历nums[i] nums[i]>nums[i-1]则f[i]=g[i-1]+1
反之则g[i]=f[i-1]+1

设计一个二维的dp[i][j]为以i j为结尾的最长等差数列的长度
先遍历i 再遍历j 因为这样我们可以一边填dp[i][j],一边将离倒数第二个数nums[i]最近的满足nums[i]-nums[j]=nums[k]-nums[i],的k值(即索引)记录在hash[nums[k]]中,这样的话只要是和倒数第二个数nums[i]有关的,无论倒数第一个数nums[j]是谁 都可以通过hash来找
填入hash的时机在遍历每个nums[i]后
同样构造一个变量跟踪记录最大值

dp[i]表示以i结尾的最长等差子序列的长度
正常做是固定最后一个元素 然后从前往后找
发现等差的就加上 发现最大的就记下来
正常做法会超时
优化做法维护一个hash[nums[i]]表示以nums[i]结尾的最长等差子序列的长度
因为我们是从前往后填hash 所以每次越往后的值都会覆盖掉前面的
越往后的值肯定是离dp[i]更近的

这题也是利用一个hash表 用哈希表找到需要的值的索引
可以先初始化 把所有的nums[i]的索引i填入hash[nums[i]]
也可以一边填表一边填hash

定义dp[i][j]为将以i开头j结尾的字串变为回文串的最少插入次数
从后往前遍历 以便得到值
若s[i]==s[j]
则dp[i][j]=dp[i+1][j-1]
因为i位置和j位置已经构成字符串 就看他内层的了
若不等于
则等于dp[i+1][j]和dp[i][j-1]比较小的 因为两边各自抵消另一个都可以看前面二者

找等差子序列的个数
dp[i][j]代表i开头j结尾的等差子序列的个数
正常也需要向前一个个找能和i位置j位置构成等差子序列的元素的dp值
优化做法是将所有的索引都放进去
而且要定义为long long 不然可能溢出

dp[i][j]表示s1的[0,i]区间及s2的[0,j]区间的所有子序列中,公共子序列的长度
根据两边最后一个位置的情况动态规划
若s1[i]==s2[j]
则dp[i][j]=dp[i-1][j-1]+1等于它们上一个位置的公共子序列+1
若不同则等于dp[i-1][j]和dp[i][j-1]的较大者

dp[i][j]表示:s字符串[0,j]区间内所有的子序列中,有多少个t字符串[0,i]区间的字符串
根据s的子序列最后一个位置包不包含s[j]来构建状态转移方程
如果当前的dp[i][j]肯定有dp[i][j-1]的值 因为新加了一个s[j]肯定更有匹配能力,前面到j-1为止的子序列有多少个能匹配到i,加一个肯定也能
然后根据s[j]等不等于t[i],如果等于,说明有dp[i-1][j-1]数量个子序列能匹配字符串(最后一个被解决了)

dp[i][j]表示p[0,j]的字符串能否匹配s[0,i]位置的字符串
状态转移方程的填表方式为
遇到s[i]和p[j]
如果相等 则依靠dp[i-1][j-1]
若p[j]=='?'
则为dp[i][j-1]
若p[j]=='*'
则为dp[i-1][j]||dp[i][j-1]
因为*可以匹配任意多个
则若p[j]能匹配到s[i-1]那肯定能匹配完
若j-1能匹配i j也能匹配空串
初始化时 所有连续的*都能匹配空串
则dp[0][j]=1 当*连续

本题和上一题不同的是 初始化时要看字符前面有没有* 要是有则dp[0][x]=dp[0][x-2]
遍历时注意三种状态
s[i-1]==p[j-1]时
则dp[i][j]=dp[i-1][j-1]
p[j-1]=='.'时
dp[i][j]=dp[i-1][j-1]
p[j-1]=='*'时 有三种情况
若dp[i][j-2]为真 则到j-2位置就能匹配上
不然就检查上一个位置
若p[j-2]=='.'就看dp[i-1][j-1]
若p[j-2]==s[i-1]也看dp[i-1][j-1]

dp[i][j]为s1的0到i的子串和s2的0到j的子串能不能拼凑出s3的0到i+j的字符串
状态转移时
遍历i与j
当s1[i]==s3[i+j-1]时
若dp[i-1][j]为真则dp[i][j]为真
当s2[j]==s3[i+j-1]时
若dp[i][j-1]为真则dp[i][j]为真

转换一下 改成求公共子序列acill码最大和
dp[i][j]为分别到i j位置的公共子序列的acill码最大和
状态转移时 四种情况
最大值有i 有j
那一定是因为s1[i]==s2[j] dp有dp[i-1][j-1]+s1[i]
最大值有i 无j
也许dp[i][j-1]的公共子序列acill码最大和更大
最大值无i 有j
也许dp[i-1][j]的公共子序列acill码最大和更大
01背包问题
dp[i][j]表示在前i个物品中挑选 总体积不超过j的最大值
遍历每个物品nums[i],考虑选择它与不选它中的最大值

dp[i][j]表示 从前i个数中选 所有的选法中 能否凑成j这个数
遍历每个i
dp[i][j]的值为不选i和选i且j-nums[i]>=0的正值
初始化应该将所有dp[i][0]置为1
因为任意个数可组成0
4万+

被折叠的 条评论
为什么被折叠?



