一、解决思路
与之前的dp问题相比,给我三个最大的不同感受是:
1、考虑能否自成一组,毕竟一个也是子序列,子数组。所以在很多的dp表填写中需要考虑只有一个的情况。
2、由于子数组子序列是连续的,所以有一些题可以利用连续性解决问题。就比如怎么找到最长等差数列,因为差值是固定的所以每次判断都只要判断三个数的两个差值是否相同,还有最长湍流子数组问题,也是利用了符号的传递性(之后会讲)
3、而且连续真的给解决问题提供了极大便利。我觉得像是一种非黑即白的解决方式。比如数组的求和,求积等,不是最大就是最小,不是正数就是负数。在解决环形问题时,由于是连续的,选中的一段区间 [i, j] 既可以考虑 [i, j] 的dp情况,也可以考虑 [j + 1, n - 1] 加上 [0, i - 1] 的环形数组问题。所以在考虑dp[i]表示时也可以考虑题目中要我们求的"最大",也可以利用连续再维护一个“最小”,有利于解决问题。
二、例题
1、最大子数组和
53. 最大子数组和 - 力扣(LeetCode)
这就是要考虑一个也是子数组的情况
2、最大环形子数组和
918. 环形子数组的最大和 - 力扣(LeetCode)
非黑即白 + 求最大也可以维护一个求最小
因为最大的情况不一定存在在连续的数组中,也有可能在不连续的,所以需要维护两个数组,记录连续数组的最大最小值,以此来获得连续和不连续数组的最大值,进行比较后返回。
3、乘积最大子数组
152. 乘积最大子数组 - 力扣(LeetCode)
求正数也可以维护一个负数
考虑到最后结果里面可能会有偶数个负数组成的最大正数,所以需要维护两个数组,一个正数用于返回结果,一个负数用于 nums[i] 是负数时能找到最大正数数组。
4、乘积为正数的最长子数组的长度
1567. 乘积为正数的最长子数组长度 - 力扣(LeetCode)
求正数也可以维护一个负数
考虑到最后结果里面可能会有偶数个负数组成的最长正数,所以需要维护两个数组,一个正数用于返回结果,一个负数用于 nums[i] 是负数时能找到最长正数数组长度。
5、等差数列划分
413. 等差数列划分 - 力扣(LeetCode)
差值的连续性
而且每一次新增一个等差数列的数字就要 + dp[i]
6、最长湍流子数组
978. 最长湍流子数组 - 力扣(LeetCode)
符号的连续性
而且注意到如果不分两个数组的方法一很复杂(我也对着错误用例一步步完善才解决),所以不妨把情况分的细致一点代码也简单。
7、单词拆分
139. 单词拆分 - 力扣(LeetCode)
非黑即白
可以把数组分成两个部分考虑也是在子数组子序列中常见的方式,这也是非黑即白的一种。
8、环绕字符中唯一子字符串个数
467. 环绕字符串中唯一的子字符串 - 力扣(LeetCode)
这道题不仅是连续性,而且还要解决一个问题:去重
去重的思路:找到规律重复的子序列结尾都是一样的字符,那么结尾一样的只要加一次,加最大个数的就行。